package com.dhecp.project.logstics.service.impl;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URL;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

import javax.imageio.ImageIO;

import com.dhecp.common.utils.sql.SqlUtil;
import com.dhecp.project.business.domain.*;
import com.dhecp.project.logstics.mapper.*;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFPatriarch;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dhecp.common.config.Global;
import com.dhecp.common.core.domain.AjaxResult;
import com.dhecp.common.utils.MessageUtils;
import com.dhecp.common.utils.RandomValueUtils;
import com.dhecp.common.utils.StringUtils;
import com.dhecp.core.constant.DataFiltering;
import com.dhecp.core.constant.ModuleTable;
import com.dhecp.core.utils.ExportExcelUtils;
import com.dhecp.core.utils.PageUtils;
import com.dhecp.framework.util.ShiroUtils;
import com.dhecp.project.business.mapper.FbaPlanOrderMapper;
import com.dhecp.project.business.mapper.LogsticsPatternDetailsMapper;
import com.dhecp.project.business.mapper.LogsticsPatternMapper;
import com.dhecp.project.business.mapper.ProductBasisMapper;
import com.dhecp.project.common.domain.ModuleNidAndBid;
import com.dhecp.project.common.mapper.ModuleNidAndBidMapper;
import com.dhecp.project.common.service.impl.BaseModuleServiceImpl;
import com.dhecp.project.logstics.domain.FbaBox;
import com.dhecp.project.logstics.domain.FbaBoxDetail;
import com.dhecp.project.logstics.domain.FbaDispatch;
import com.dhecp.project.logstics.domain.FbaSpellTicket;
import com.dhecp.project.logstics.domain.FbaSpellTicketDetail;
import com.dhecp.project.logstics.domain.PrintList2;
import com.dhecp.project.logstics.service.FbaBoxService;
import com.dhecp.project.system.domain.SysDictionaryForExport;
import com.dhecp.project.system.service.SysDictionaryForFieldService;

/**
 * 头程计划单 服务层
 * @Author fxz
 * @Date 2022/9/23
 */
@Service
public class FbaBoxServicelmpl extends BaseModuleServiceImpl implements FbaBoxService {


    @Autowired
    private FbaBoxMapper fbaBoxMapper;
    @Autowired
    private FbaBoxDetailMapper fbaBoxDetailMapper;

    @Autowired
    private SysDictionaryForFieldService dictionaryForFieldService;

    private String moduleTable = ModuleTable.FBA_DISPATCH;
    private String moduleTableFH = ModuleTable.FBA_BOXFH;
    private String moduleTableBOX = ModuleTable.FBA_BOX;

    @Autowired
    private ModuleNidAndBidMapper moduleNidAndBidMapper;

    @Autowired
    private FbaDispatchMapper fbaDispatchMapper;

    @Autowired
    private FbaPlanOrderMapper fbaPlanOrderMapper;

    @Autowired
    private ProductBasisMapper productBasisMapper;

    @Autowired
    private LogsticsPatternDetailsMapper logsticsPatternDetailsMapper;

    @Autowired
    private LogsticsPatternMapper logsticsPatternMapper;

    @Autowired
    private LogsticsMmodeMapper logsticsMmodeMapper;

    @Autowired
    private LogsticsMmodeGradsMapper logsticsMmodeGradsMapper;

    @Autowired
    private LogsticsMmodeDetailsMapper logsticsMmodeDetailsMapper;

    @Autowired
    private FbaSpellTickMapper fbaSpellTickMapper;

    @Autowired
    private FbaSpellTicketDetailMapper fbaSpellTicketDetailMapper;

    @Autowired
    private LogsticsMmodeCkMapper logsticsMmodeCkMapper;




    /**
     * 查询头程计划单
     * @param params
     * @return
     * @throws Exception
     */
    @Override
    public List<FbaBox> queryList(Map<String, Object> params) throws Exception {
        //特殊字段商品编码修改查询详情有关联的数据
        if (params.get("commodityCode") != null && !params.get("commodityCode").equals("")){
            params.put("commodityCode1",params.get("commodityCode"));
            params.put("commodityCode","");
        }
        params.put(DataFiltering.TABLE_ALIAS, "t1");	//查询表别名
        params.put(DataFiltering.DATA_WHERE, dictionaryForFieldService.getWhereStr(params));	//常规查询条件SQL语句
        params.put(DataFiltering.DATA_SCODE, dictionaryForFieldService.getDataScode(params));	//数据权限查询条件SQL语句

        if (params.get("field") == null || params.get("field") == ""){
            String orderBy = "t1.createTime DESC";
            PageUtils.startPageOrder(orderBy);
        }else{
            if (params.get("field").equals("codePlan") || params.get("field").equals("creationMethod")){
                params.put(DataFiltering.TABLE_ALIAS, "fpo");
            }else if (params.get("field").equals("bUserName")){
                params.put(DataFiltering.TABLE_ALIAS, "u2");
                params.put("field", "userName");
            }else if (params.get("field").equals("bDeptName")){
                params.put(DataFiltering.TABLE_ALIAS, "d3");
                params.put("field", "orgName");
            }
            String orderBy = params.get(DataFiltering.TABLE_ALIAS)+ "."+ SqlUtil.escapeOrderBySql(params.get("field").toString()) + " "+  params.get("order");
            PageUtils.startPageOrder(orderBy);
        }

        return fbaBoxMapper.select(params);
    }


    /**
     * 查询头程计划单
     * @param params
     * @return
     * @throws Exception
     */
    @Override
    public List<FbaBoxDetail> querySonList(Map<String, Object> params) {
        return fbaBoxDetailMapper.queryList(params);
    }


	@Override
	public FbaBox queryByBid(String bid) {
		return fbaBoxMapper.queryByBid(bid);
	}


    /**
     * 新增头程计划单
     * @param params
     * @return
     */
    @Override
    public AjaxResult insertFbaBox(Map<String, Object> params) {
        if (StringUtils.isEmpty(params)) {
            return AjaxResult.error("数据提交失败，必填参数有误！");
        }

        FbaBox entity = JSON.parseObject(JSON.toJSONString(params), FbaBox.class);
        entity.setGuid(RandomValueUtils.getGUID());
        entity.setCreateUser(ShiroUtils.getUserId());
        entity.setCreateTime(new Date());
//        entity.setUpdateUser(ShiroUtils.getUserId());
//        entity.setUpdateTime(new Date());
        if (entity.getGuid() == null || "".equals(entity.getGuid())){
            entity.setGuid(RandomValueUtils.getGUID());
        }

        if (entity.getCode() == null || entity.getCode().length() == 0) {
            return AjaxResult.error("数据提交失败，必填参数有误！");
        }

        fbaBoxMapper.insertFbaBox(entity);
        return AjaxResult.success("操作成功");
    }

    @Override
    public FbaBox queryFirstRecord(Map<String, Object> params) throws Exception {
        params.put(DataFiltering.TABLE_ALIAS, "t1");    //查询表别名
        params.put(DataFiltering.DATA_SCODE, dictionaryForFieldService.getDataScode(params));    //数据权限查询条件SQL语句
        return fbaBoxMapper.selectFirstRecordByNid(params);
    }

    /**
     *@Description: 保存
     *@Param: [params] moduleTable 必要参数：功能唯一标识
     *@Param: [params] infoMap 必要参数：非网格字段（包括头部、底部所有显示和隐藏的字段）
     *@Param: [params] infoItems 必要参数：对应实体类的json格式字符串
     *@return: com.dhecp.common.core.domain.AjaxResult
     *@Author: hlf
     *@date: 2022-05-09 10:10
     */
    @SuppressWarnings("unchecked")
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public AjaxResult saveData(Map<String, Object> params) {
        if (params.get("infoMap") == null || params.get("infoMap") == "") {
            return AjaxResult.error(MessageUtils.message("module.error.lack.infomap"));
        }
        FbaBox fbaBox = JSON.parseObject(params.get("infoMap").toString(), FbaBox.class);
        FbaBox fbaBox1 = fbaBoxMapper.queryFirstByGuid(fbaBox.getGuid());
        if (fbaBox1.getState().equals("1")){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error(fbaBox1.getCode()+"该头程装箱单已完成不允许修改,请核实后在操作!");
        }
        if (!fbaBox1.getState().equals(fbaBox.getState())){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error(fbaBox1.getCode()+"该头程装箱单状态已更变,请刷新页面后在操作!");
        }
        if (!fbaBox1.getIsBinning().equals(fbaBox.getIsBinning())){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error(fbaBox1.getCode()+"该头程装箱单状态已更变,请刷新页面后在操作!");
        }
        if (fbaBox.getLoadDelivery().equals("1")){
            fbaBox.setLoadDelivery("是");
        }
        if (fbaBox.getLoadDelivery().equals("0")){
            fbaBox.setLoadDelivery("否");
        }
        //修改装箱详情
        fbaBoxMapper.updateByGuid(fbaBox);
        //返回id用于前端查询
        String resGuid = fbaBox.getGuid();

        List<FbaBoxDetail> fbaBoxDetailList = JSON.parseArray(params.get("infoItems").toString(), FbaBoxDetail.class);
        List<FbaBoxDetail> repeat = fbaBoxDetailList.stream().filter(fbaBoxDetail2 -> fbaBoxDetail2.getSerial().equals("箱重(kg)")).collect(Collectors.toList());
        List<FbaBoxDetail> casesGaugeLength = fbaBoxDetailList.stream().filter(fbaBoxDetail2 -> fbaBoxDetail2.getSerial().equals("箱规长(cm)")).collect(Collectors.toList());
        List<FbaBoxDetail> tankGaugeWide = fbaBoxDetailList.stream().filter(fbaBoxDetail2 -> fbaBoxDetail2.getSerial().equals("箱规宽(cm)")).collect(Collectors.toList());
        List<FbaBoxDetail> boxGaugeHigh = fbaBoxDetailList.stream().filter(fbaBoxDetail2 -> fbaBoxDetail2.getSerial().equals("箱规高(cm)")).collect(Collectors.toList());
        List<FbaBoxDetail> toss = fbaBoxDetailList.stream().filter(fbaBoxDetail2 -> fbaBoxDetail2.getSerial().equals("抛重(kg)")).collect(Collectors.toList());
        List<FbaBoxDetail> price = fbaBoxDetailList.stream().filter(fbaBoxDetail2 -> fbaBoxDetail2.getSerial().equals("单箱采购总价(￥)")).collect(Collectors.toList());
        List<FbaBoxDetail> fbaBoxDetailListNew = new ArrayList<>();
        FbaBoxDetail fbaBoxDetailNew;
        //删除装箱详情数据
        fbaBoxDetailMapper.deleteCodeBox(fbaBox.getCode());

        //根据头程箱数新增
        for (int j = 0; j < fbaBox.getNumBox(); j++) {
            fbaBoxDetailNew = new FbaBoxDetail();
            fbaBoxDetailNew.setGuid(RandomValueUtils.getGUID());
            //关联头程计划详情
            fbaBoxDetailNew.setCodeBox(fbaBox.getCode());
            fbaBoxDetailNew.setCodeShipment(fbaBox.getCodeShipment());
            fbaBoxDetailNew.setBoxIndex(j);
            fbaBoxDetailNew.setBUser(ShiroUtils.getMandatorId());
            fbaBoxDetailNew.setBDept(ShiroUtils.getMandatorDeptPath());
            fbaBoxDetailNew.setDeleted(0);
            fbaBoxDetailNew.setCreateTime(new Date());
            fbaBoxDetailNew.setCreateUser(ShiroUtils.getMandatorId());
            List<FbaBoxDetail> productInfoList = JSON.parseArray(params.get("infoItems").toString(), FbaBoxDetail.class).stream().filter(fbaBoxDetail2 -> fbaBoxDetail2.getScrapData().equals("0")).collect(Collectors.toList());
            switch (j) {
                case 0:
                    valuation(fbaBoxDetailNew,repeat.get(0).getNumRealityDeliver1(),
                            casesGaugeLength.get(0).getNumRealityDeliver1(), tankGaugeWide.get(0).getNumRealityDeliver1(), boxGaugeHigh.get(0).getNumRealityDeliver1(),
                            toss.get(0).getNumRealityDeliver1(),price.get(0).getNumRealityDeliver1(),productInfoList,j);
                    break;
                case 1:
                    valuation(fbaBoxDetailNew, repeat.get(0).getNumRealityDeliver2(),
                            casesGaugeLength.get(0).getNumRealityDeliver2(), tankGaugeWide.get(0).getNumRealityDeliver2(), boxGaugeHigh.get(0).getNumRealityDeliver2(),
                            toss.get(0).getNumRealityDeliver2(),price.get(0).getNumRealityDeliver2(),productInfoList,j);
                    break;
                case 2:
                    valuation(fbaBoxDetailNew, repeat.get(0).getNumRealityDeliver3(),
                            casesGaugeLength.get(0).getNumRealityDeliver3(), tankGaugeWide.get(0).getNumRealityDeliver3(), boxGaugeHigh.get(0).getNumRealityDeliver3(),
                            toss.get(0).getNumRealityDeliver3(),price.get(0).getNumRealityDeliver3(),productInfoList,j);
                    break;
                case 3:
                    valuation(fbaBoxDetailNew,  repeat.get(0).getNumRealityDeliver4(),
                            casesGaugeLength.get(0).getNumRealityDeliver4(), tankGaugeWide.get(0).getNumRealityDeliver4(), boxGaugeHigh.get(0).getNumRealityDeliver4(),
                            toss.get(0).getNumRealityDeliver4(),price.get(0).getNumRealityDeliver4(),productInfoList,j);
                    break;
                case 4:
                    valuation(fbaBoxDetailNew,  repeat.get(0).getNumRealityDeliver5(),
                            casesGaugeLength.get(0).getNumRealityDeliver5(), tankGaugeWide.get(0).getNumRealityDeliver5(), boxGaugeHigh.get(0).getNumRealityDeliver5(),
                            toss.get(0).getNumRealityDeliver5(),price.get(0).getNumRealityDeliver5(),productInfoList,j);
                    break;
                case 5:
                    valuation(fbaBoxDetailNew,  repeat.get(0).getNumRealityDeliver6(),
                            casesGaugeLength.get(0).getNumRealityDeliver6(), tankGaugeWide.get(0).getNumRealityDeliver6(), boxGaugeHigh.get(0).getNumRealityDeliver6(),
                            toss.get(0).getNumRealityDeliver6(),price.get(0).getNumRealityDeliver6(),productInfoList,j);
                    break;
                case 6:
                    valuation(fbaBoxDetailNew, repeat.get(0).getNumRealityDeliver7(),
                            casesGaugeLength.get(0).getNumRealityDeliver7(), tankGaugeWide.get(0).getNumRealityDeliver7(), boxGaugeHigh.get(0).getNumRealityDeliver7(),
                            toss.get(0).getNumRealityDeliver7(),price.get(0).getNumRealityDeliver7(),productInfoList,j);
                    break;
                case 7:
                    valuation(fbaBoxDetailNew,  repeat.get(0).getNumRealityDeliver8(),
                            casesGaugeLength.get(0).getNumRealityDeliver8(), tankGaugeWide.get(0).getNumRealityDeliver8(), boxGaugeHigh.get(0).getNumRealityDeliver8(),
                            toss.get(0).getNumRealityDeliver8(),price.get(0).getNumRealityDeliver8(),productInfoList,j);
                    break;
                case 8:
                    valuation(fbaBoxDetailNew, repeat.get(0).getNumRealityDeliver9(),
                            casesGaugeLength.get(0).getNumRealityDeliver9(), tankGaugeWide.get(0).getNumRealityDeliver9(), boxGaugeHigh.get(0).getNumRealityDeliver9(),
                            toss.get(0).getNumRealityDeliver9(),price.get(0).getNumRealityDeliver9(),productInfoList,j);
                    break;
                case 9:
                    valuation(fbaBoxDetailNew,  repeat.get(0).getNumRealityDeliver10(),
                            casesGaugeLength.get(0).getNumRealityDeliver10(), tankGaugeWide.get(0).getNumRealityDeliver10(), boxGaugeHigh.get(0).getNumRealityDeliver10(),
                            toss.get(0).getNumRealityDeliver10(),price.get(0).getNumRealityDeliver10(),productInfoList,j);
                    break;
            }
            //将其他箱数的值统一赋值一个值上
            fbaBoxDetailNew.setProductInfo(JSONArray.toJSONString(productInfoList));
            fbaBoxDetailListNew.add(fbaBoxDetailNew);
        }

        fbaBoxDetailMapper.batchInsert(fbaBoxDetailListNew);
        return AjaxResult.success(MessageUtils.message("module.success.issuccess"),resGuid);
    }


    /**
     *@Description: 装箱清单导入保存
     *@Param: [params] moduleTable 必要参数：功能唯一标识
     *@Param: [params] infoMap 必要参数：非网格字段（包括头部、底部所有显示和隐藏的字段）
     *@Param: [params] infoItems 必要参数：对应实体类的json格式字符串
     *@return: com.dhecp.common.core.domain.AjaxResult
     *@Author: fxz
     *@date: 2023-04-25 10:10
     */
    @SuppressWarnings("unchecked")
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public AjaxResult saveDataInbound(Map<String, Object> params) {
        if (params.get("infoItems") == null || params.get("infoItems") == "") {
            return AjaxResult.error(MessageUtils.message("module.error.lack.infomap"));
        }
        if (params.get("shipmentId") == null || params.get("shipmentId") == "") {
            return AjaxResult.error("选择数据FBA编号为空或者创建方式为手动,不允许操作该功能,请核实后再操作!");
        }
        String shipmentId = params.get("shipmentId").toString();
        FbaBox fbaBox1 = fbaBoxMapper.queryFirstByShipmentId(shipmentId);
        if (!fbaBox1.getState().equals("0")){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error(shipmentId+"该FBA号当前状态不允许修改,请核实后在操作!");
        }

        List<FbaBoxDetail> fbaBoxDetailList = JSON.parseArray(params.get("infoItems").toString(), FbaBoxDetail.class);
        List<FbaBoxDetail> repeat = fbaBoxDetailList.stream().filter(fbaBoxDetail2 -> fbaBoxDetail2.getSerial().equals("箱重(kg)")).collect(Collectors.toList());
        List<FbaBoxDetail> casesGaugeLength = fbaBoxDetailList.stream().filter(fbaBoxDetail2 -> fbaBoxDetail2.getSerial().equals("箱规长(cm)")).collect(Collectors.toList());
        List<FbaBoxDetail> tankGaugeWide = fbaBoxDetailList.stream().filter(fbaBoxDetail2 -> fbaBoxDetail2.getSerial().equals("箱规宽(cm)")).collect(Collectors.toList());
        List<FbaBoxDetail> boxGaugeHigh = fbaBoxDetailList.stream().filter(fbaBoxDetail2 -> fbaBoxDetail2.getSerial().equals("箱规高(cm)")).collect(Collectors.toList());
        List<FbaBoxDetail> fbaBoxDetailListNew = new ArrayList<>();
        FbaBoxDetail fbaBoxDetailNew;

        //根据头程货件单号查询货件详情信息
        params.put("codeShipment",fbaBox1.getCodeShipment());
        List<FbaBoxDetail> queryList = fbaBoxDetailMapper.select(params);

        Map<String, Object> params11 = new HashMap<String, Object>();
        params11.put("guid",fbaBox1.getLogisticsMmodeGuid());
        //查询物流方式
        LogisticsMmode logisticsMmode = logsticsMmodeMapper.queryFirstByGuid(params11);
        //获取物流方式详情
        Map<String, Object> params4 = new HashMap<String, Object>();
        params4.put("logisticsMmodeGuid",fbaBox1.getLogisticsMmodeGuid());
        List<LogisticsMmodeDetails> textureList = logsticsMmodeDetailsMapper.findLogisticsMmodeDetails(params4);
        //获取物流方式梯度
        List<LogisticsMmodeGrads> logisticsMmodeGradList = logsticsMmodeGradsMapper.findLogisticsMmodeGrads(params4);
        List<LogisticsMmodeGrads> logisticsMmodeGrads  = logisticsMmodeGradList.stream().filter(logisticsMmodeGrads1 ->
                "WLFS".equals(logisticsMmodeGrads1.getType())).collect(Collectors.toList());
        List<LogisticsMmodeGrads> logisticsMmodeInfoItems  = logisticsMmodeGradList.stream().filter(logisticsMmodeGrads1 ->
                "WLFSTDJZ".equals(logisticsMmodeGrads1.getType())).collect(Collectors.toList());
        List<LogisticsMmodeCk> logisticsMmodeCkList = logsticsMmodeCkMapper.findLogisticsMmodeCk(params4);

        params4.remove("logisticsMmodeGuid");
        params4.put("type","WLPMTD");
        //获取品名梯度详情
        List<LogisticsMmodeGrads> wlpmtdList = logsticsMmodeGradsMapper.findLogisticsMmodeGrads(params4);

        if (casesGaugeLength.size()==0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error(shipmentId+"该FBA号缺少箱重信息,请核实后在操作!");
        }
        //导入的箱子数据
        List<FbaBoxDetail> productInfoList = JSON.parseArray(params.get("infoItems").toString(), FbaBoxDetail.class).stream().filter(fbaBoxDetail2 -> StringUtils.isNumeric(fbaBoxDetail2.getSerial())).collect(Collectors.toList());
        if (queryList.size() != productInfoList.size()){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error(shipmentId+"该FBA号导入的商品信息不匹配,请核实后在操作!");
        }
        //错误数据
        List<FbaBoxDetail> errData = productInfoList.stream().filter(fbaBoxDetail2 -> !fbaBoxDetail2.getNumPlanDeliver().equals(fbaBoxDetail2.getNumRealityDeliver())).collect(Collectors.toList());
        if (errData.size() >0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error(shipmentId+"该FBA号实际发货数量不等于计划发货数量,请核实后在操作!");
        }
        //箱重的箱子重量数据
        List<BigDecimal> boxList1 = (List<BigDecimal>) JSON.parse(repeat.get(0).getBoxList());
        //箱长的箱子重量数据
        List<BigDecimal> casesBoxList = (List<BigDecimal>) JSON.parse(casesGaugeLength.get(0).getBoxList());
        //箱宽的箱子重量数据
        List<BigDecimal> wideBoxList = (List<BigDecimal>) JSON.parse(tankGaugeWide.get(0).getBoxList());
        //箱高的箱子重量数据
        List<BigDecimal> hgighBoxList = (List<BigDecimal>) JSON.parse(boxGaugeHigh.get(0).getBoxList());

        //每个商品的箱子数据
        List<BigDecimal> nameGoodsCnBox;

        //单箱采购总价
        BigDecimal priceSingleBoxReqTol;

        //根据头程箱数新增
        for (int j = 0; j < boxList1.size(); j++) {
            fbaBoxDetailNew = new FbaBoxDetail();
            fbaBoxDetailNew.setGuid(RandomValueUtils.getGUID());
            //关联头程计划详情
            fbaBoxDetailNew.setCodeBox(fbaBox1.getCode());
            fbaBoxDetailNew.setCodeShipment(fbaBox1.getCodeShipment());
            fbaBoxDetailNew.setBoxIndex(j);
            fbaBoxDetailNew.setBUser(ShiroUtils.getMandatorId());
            fbaBoxDetailNew.setBDept(ShiroUtils.getMandatorDeptPath());
            fbaBoxDetailNew.setDeleted(0);
            fbaBoxDetailNew.setCreateTime(new Date());
            fbaBoxDetailNew.setCreateUser(ShiroUtils.getMandatorId());

            priceSingleBoxReqTol = BigDecimal.ZERO;
            //将每箱子的数据赋值到NumRealityDeliver字段上
            for (int i = 0; i < queryList.size(); i++) {
                if (!queryList.get(i).getCommodityCode().equals(productInfoList.get(i).getCommodityCode())
                || !queryList.get(i).getSku().equals(productInfoList.get(i).getSku())
                ||!queryList.get(i).getFnsku().equals(productInfoList.get(i).getFnsku())
                || !queryList.get(i).getAsin().equals(productInfoList.get(i).getAsin())){
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return AjaxResult.error(shipmentId+"该FBA号商品信息数据异常,请按照模板导入数据!");
                }
                nameGoodsCnBox = (List<BigDecimal>) JSON.parse(productInfoList.get(i).getBoxList());
                queryList.get(i).setNumRealityDeliver(String.valueOf(nameGoodsCnBox.get(j)).equals("0")?"":String.valueOf(nameGoodsCnBox.get(j)));
                queryList.get(i).setSerial(productInfoList.get(i).getSerial());
                queryList.get(i).setBoxList(productInfoList.get(i).getBoxList());
                //计算单箱采购单价
                priceSingleBoxReqTol = priceSingleBoxReqTol.add(new BigDecimal(String.valueOf(nameGoodsCnBox.get(j))).multiply(new BigDecimal(queryList.get(i).getPriceIn())));
            }
            if (String.valueOf(boxList1.get(j)).equals("0")){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error(shipmentId+"该FBA号箱重信息不允许填入0或者空值,请核实后在操作!");
            }
            if (String.valueOf(casesBoxList.get(j)).equals("0")){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error(shipmentId+"该FBA号箱规长信息不允许填入0或者空值,请核实后在操作!");
            }
            if (String.valueOf(wideBoxList.get(j)).equals("0")){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error(shipmentId+"该FBA号箱规宽信息不允许填入0或者空值,请核实后在操作!");
            }
            if (String.valueOf(hgighBoxList.get(j)).equals("0")){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error(shipmentId+"该FBA号箱规高信息不允许填入0或者空值,请核实后在操作!");
            }
            if (new BigDecimal(String.valueOf(hgighBoxList.get(j))).compareTo(new BigDecimal(120)) == 1
                    || new BigDecimal(String.valueOf(wideBoxList.get(j))).compareTo(new BigDecimal(120)) == 1
                    || new BigDecimal(String.valueOf(casesBoxList.get(j))).compareTo(new BigDecimal(120)) == 1
                    || new BigDecimal(String.valueOf(boxList1.get(j))).compareTo(new BigDecimal(120)) == 1){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error(shipmentId+"该FBA号箱规信息只允许小于120的数值,请核实后在操作!");
            }
            //a+2*b+2*c≤260的限制（abc代表箱规的长宽高）
            BigDecimal xzNum = BigDecimal.ZERO;
            xzNum = new BigDecimal(String.valueOf(casesBoxList.get(j))).add(new BigDecimal(2).multiply(new BigDecimal(String.valueOf(wideBoxList.get(j)))))
                    .add(new BigDecimal(2).multiply(new BigDecimal(String.valueOf(hgighBoxList.get(j)))));
            if (xzNum.compareTo(new BigDecimal("260")) > 0 ){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error("第"+ (j+1) + "箱填写的尺寸已超过控制范围，请核实!");
            }
            fbaBoxDetailNew.setWeight(String.valueOf(boxList1.get(j)));
            fbaBoxDetailNew.setLength(String.valueOf(casesBoxList.get(j)));
            fbaBoxDetailNew.setWidth(String.valueOf(wideBoxList.get(j)));
            fbaBoxDetailNew.setHeight(String.valueOf(hgighBoxList.get(j)));
            //计算抛重
            BigDecimal weighVol =
                    (new BigDecimal(String.valueOf(casesBoxList.get(j))).multiply(new BigDecimal(String.valueOf(wideBoxList.get(j)))
                            .multiply(new BigDecimal(String.valueOf(hgighBoxList.get(j))))))
                            .divide(new BigDecimal(logisticsMmode.getCoefficientWeight()),2, RoundingMode.HALF_UP);
            fbaBoxDetailNew.setWeightVol(String.valueOf(weighVol));
            fbaBoxDetailNew.setPriceSingleBoxReq(priceSingleBoxReqTol);
            //将其他箱数的值统一赋值一个值上
            fbaBoxDetailNew.setProductInfo(JSONArray.toJSONString(queryList));
            fbaBoxDetailListNew.add(fbaBoxDetailNew);
        }

        List<FbaBoxDetail> fbaBoxDetailListInset = new ArrayList<>();
        //历史的商品信息
        List<FbaBoxDetail> fbaBoxDetailListOld;
        BigDecimal weightReal;
        BigDecimal weightVol;
        BigDecimal predVal;
        BigDecimal weightCal;
        BigDecimal weightCalNew;
        BigDecimal max_result;
        BigDecimal texture;
        BigDecimal weightPrice;
        BigDecimal phweightPrice;
        BigDecimal priceClearanceOpePrice;
        BigDecimal tradeNamePro;
        Boolean numWeightCal;
        Integer numProName;
        Integer num;
        Double numFreeProName;
        BigDecimal priceTranCalWeightPredict;
        BigDecimal warehouseSurcharge;
        BigDecimal weightVolPredictNew;
        String surchargeMaterialMax;
        BigDecimal weightCalBySingle;
        List<LogisticsMmodeGrads> tdjzPrice;
        List<LogisticsMmodeGrads> pzjzPrice;
        List<LogisticsMmodeGrads> phjzPrice;
        List<LogisticsMmodeGrads> qgPrice;
        Set<String> gradeNum;
        //总箱重
        weightReal = BigDecimal.ZERO;
        //总抛重
        weightVol = BigDecimal.ZERO;
        //最大的材质值
        texture = BigDecimal.ZERO;
        //最大值材质名称
        surchargeMaterialMax = "";
        //实际计重之和
        weightCal = BigDecimal.ZERO;
        //最大值
        max_result = BigDecimal.ZERO;
        //实际计重约分
        weightCalNew = BigDecimal.ZERO;
        //抛货系数
        predVal = BigDecimal.ZERO;
        //计重单价
        weightPrice = BigDecimal.ZERO;
        //抛重梯度计重单价
        weightVolPredictNew = BigDecimal.ZERO;
        //抛重计重单价
        phweightPrice = BigDecimal.ZERO;
        //实际计重费
        priceTranCalWeightPredict = BigDecimal.ZERO;
        //仓库附加计重费用
        warehouseSurcharge = BigDecimal.ZERO;
        //品名数除上限数
        tradeNamePro = BigDecimal.ZERO;
        //清关费
        priceClearanceOpePrice = new BigDecimal(100);
        //品名判断数值
        numWeightCal = true;
        //实际品名数
        numProName = 0;
        //超出品名
        num = 0;
        //实际品名免费数
        numFreeProName = 0.0;
        //品名数量
        gradeNum = new HashSet<>();
        for (int boxIndex = 0; boxIndex < fbaBoxDetailListNew.size(); boxIndex++) {
            //实际的商品信息
            fbaBoxDetailListOld = JSON.parseArray(fbaBoxDetailListNew.get(boxIndex).getProductInfo(), FbaBoxDetail.class);

            //计算抛重和实重的数据和采购价
            weightReal = weightReal.add(new BigDecimal(fbaBoxDetailListNew.get(boxIndex).getWeight()));
            weightVol = weightVol.add(new BigDecimal(fbaBoxDetailListNew.get(boxIndex).getWeightVol()));
            //MAX（单箱抛重，单箱起重）
            weightVolPredictNew = weightVolPredictNew.add(logisticsMmode.getWeightCalBySingle().max(new BigDecimal(fbaBoxDetailListNew.get(boxIndex).getWeightVol())));

            //物流方式==是
            if (fbaBox1.getStateShareTicketName().equals("是")) {
                if (fbaBox1.getLogisticsType().equals("快递")) {
                    //实际计重=MAX（实重,抛重,单箱起重）
                    max_result = logisticsMmode.getWeightCalBySingle().max(new BigDecimal(fbaBoxDetailListNew.get(boxIndex).getWeight()));
                    max_result = max_result.max(new BigDecimal(fbaBoxDetailListNew.get(boxIndex).getWeightVol()));
                    //实际计重之和
                    weightCal = weightCal.add(precision(max_result));
                }else {
                    //实际计重=MAX（实重,单箱起重）
                    max_result = logisticsMmode.getWeightCalBySingle().max(new BigDecimal(fbaBoxDetailListNew.get(boxIndex).getWeight()));
                    //实际计重之和
                    weightCal = weightCal.add(max_result);
                }
            } else {
                if (fbaBox1.getLogisticsType().equals("快递")) {
                    //实际计重=MAX（实重,抛重,单箱起重）
                    max_result = logisticsMmode.getWeightCalBySingle().max(new BigDecimal(fbaBoxDetailListNew.get(boxIndex).getWeight()));
                    max_result = max_result.max(new BigDecimal(fbaBoxDetailListNew.get(boxIndex).getWeightVol()));
                    //实际计重之和
                    weightCal = weightCal.add(precision(max_result));
                }else {
                    //实际计重=【MAX（单箱装箱实重，单箱装箱抛重，单箱起重）先把所有箱子加起来，在进行约分向上取整】。实际计重=MAX（A1，单票起重）
                    max_result = logisticsMmode.getWeightCalBySingle().max(new BigDecimal(fbaBoxDetailListNew.get(boxIndex).getWeight()));
                    max_result = max_result.max(new BigDecimal(fbaBoxDetailListNew.get(boxIndex).getWeightVol()));
                    //实际计重之和
                    weightCal = weightCal.add(max_result);
                }
            }

            //重新计算是第几箱子
            fbaBoxDetailListNew.get(boxIndex).setBoxIndex(boxIndex);

            for (FbaBoxDetail  fbaBoxDetail1 : fbaBoxDetailListOld){
                //TODO 判断十个箱子里面的值是否有值 再来判断是否需要判断品名数
                //不一样的品名数=(商品中文、海关编码、材质中文只要一个不同)
                String join = fbaBoxDetail1.getNameGoodsCn() + '-' + fbaBoxDetail1.getCodeGoodsHs() + '-' +fbaBoxDetail1.getNameMaterialCn();
                gradeNum.add(join);

                //判断是否是混合材质
                //TODO 判断十个箱子里面的值是否有值 再来判断是否需要判断材质值
                if (fbaBoxDetail1.getNameMaterialCn().indexOf(",") == -1) {
                    //赋值材质附加费(取最大值)
                    for (int j = 0; j < textureList.size(); j++) {
                        if (textureList.get(j).getMaterialName().equals(fbaBoxDetail1.getNameMaterialCn())) {
                            if (textureList.get(j).getMaterialCost().compareTo(texture) > 0) {
                                texture = (textureList.get(j).getMaterialCost());
                                surchargeMaterialMax = (textureList.get(j).getMaterialName());
                            }
                        }
                    }
                } else {
                    String[] nameMaterialCnList = fbaBoxDetail1.getNameMaterialCn().split(",");
                    for (String nameMaterialCn : nameMaterialCnList){
                        for (int j = 0; j < textureList.size(); j++) {
                            if (textureList.get(j).getMaterialName().equals(nameMaterialCn)) {
                                if (textureList.get(j).getMaterialCost().compareTo(texture) > 0) {
                                    texture = (textureList.get(j).getMaterialCost());
                                    surchargeMaterialMax = (textureList.get(j).getMaterialName());
                                }
                            }
                        }
                    }
                }
            }
        }

        //约分
        weightVolPredictNew = precision(weightVolPredictNew);

        //是否拼票是
        if (fbaBox1.getStateShareTicketName().equals("是")) {
            //计重约分
            if (fbaBox1.getLogisticsType().equals("快递")) {
                weightCalNew = weightCal;
            }else {
                weightCalNew = precision(weightCal);
            }
            //梯度计重单价=(实际计重满足区间的值)
            BigDecimal finalWeightCalNew = weightCalNew;
            tdjzPrice = logisticsMmodeGrads.stream().filter(logisticsMmodeGrads1 -> finalWeightCalNew.compareTo(logisticsMmodeGrads1.getStartSection()) >= 0
                    && finalWeightCalNew.compareTo(logisticsMmodeGrads1.getEndSection()) <= 0).collect(Collectors.toList());
            //抛货系数=(抛重的值-计重的值)
            predVal = (weightVol.subtract(weightCalNew)).setScale(2, BigDecimal.ROUND_HALF_UP);
            //抛货计重单价=(抛货系数满足区间的值)
            BigDecimal finalPredVal = predVal;
            pzjzPrice = logisticsMmodeInfoItems.stream().filter(logisticsMmodeGrads1 -> finalPredVal.compareTo(logisticsMmodeGrads1.getStartSection()) >= 0
                    && finalPredVal.compareTo(logisticsMmodeGrads1.getEndSection()) <= 0).collect(Collectors.toList());
            //计重单价=梯度计重单价+抛重计重单价
            weightPrice = (tdjzPrice.size()!=0?tdjzPrice.get(0).getKg():BigDecimal.ZERO).add(pzjzPrice.size()!=0?pzjzPrice.get(0).getKg():BigDecimal.ZERO);

            phweightPrice = (tdjzPrice.size()!=0?tdjzPrice.get(0).getKg():BigDecimal.ZERO);

            //抛重>实重，实际计重费=MIN(实际计重*计重单价,抛货计重费)；抛重<实重，实际计重费=实际计重*计重单价；
            priceTranCalWeightPredict = (weightCalNew.multiply(weightPrice)).setScale(2, BigDecimal.ROUND_HALF_UP);
            if (weightVol.compareTo(weightReal) > 0){
                if (priceTranCalWeightPredict.compareTo(weightVolPredictNew.multiply(phweightPrice))>=0){
                    fbaBox1.setPriceTranCalWeightPredict(weightVolPredictNew.multiply(phweightPrice));
                }else {
                    fbaBox1.setPriceTranCalWeightPredict(priceTranCalWeightPredict);
                }
            }else {
                fbaBox1.setPriceTranCalWeightPredict(priceTranCalWeightPredict);
            }
            //1.实际计重<单票起重的二分之一,实际品名数=免费品名数/2&向下取整
            numWeightCal = weightCalNew.compareTo(fbaBox1.getSinglePassCrane().divide(new BigDecimal(2)))<0;
            //实际品名数
            numProName = gradeNum.size();
            if (numWeightCal){
                numFreeProName = Math.floor(fbaBox1.getNumFreeProNameNew()/2.0);
            }
            //2.实际计重>=单票起重的二分之一,实际品名数=免费品名数/2&向上取整
            if (!numWeightCal && weightCalNew.compareTo(fbaBox1.getSinglePassCrane())<0){
                numFreeProName = Math.ceil(fbaBox1.getNumFreeProNameNew()/2.0);
            }
            if (weightCalNew.compareTo(fbaBox1.getSinglePassCrane()) >= 0){
                //3.实际计重>=单票起重,实际品名数=免费品名数
                numFreeProName = fbaBox1.getNumFreeProNameNew().doubleValue();
            }
            //超出品名=实际品名-实际免费品名数
            num = numProName-numFreeProName.intValue();
            //品名免费数
            fbaBox1.setNumFreeProName(String.valueOf(numFreeProName.intValue()));
            fbaBox1.setNumProName(numProName);
            //清关费=清关费*清关占比
            if (fbaBox1.getNumMaxProName()!= 0){
                //品名数/上限数
                tradeNamePro = new BigDecimal(gradeNum.size()).divide(new BigDecimal(logisticsMmode.getNumMaxProName()),2,RoundingMode.HALF_UP);
                BigDecimal finalTradeNamePro = tradeNamePro;
                qgPrice = wlpmtdList.stream().filter(logisticsMmodeGrads1 -> finalTradeNamePro.compareTo(logisticsMmodeGrads1.getStartSection()) >= 0
                        && finalTradeNamePro.compareTo(logisticsMmodeGrads1.getEndSection()) <= 0).collect(Collectors.toList());
                priceClearanceOpePrice = qgPrice.size()!=0?qgPrice.get(0).getKg():BigDecimal.ZERO;
            }
            //预估清光费(物流方式清光费*品名占比)
            fbaBox1.setPriceClearanceOpe((logisticsMmode.getPriceClearanceOpe().multiply(priceClearanceOpePrice)).divide(new BigDecimal(100),2,RoundingMode.HALF_UP));
            //清光费单价
            fbaBox1.setPriceClearanceOpePrice(logisticsMmode.getPriceClearanceOpe());
        } else {
            //计重约分
            if (fbaBox1.getLogisticsType().equals("快递")) {
                weightCalNew = weightCal;
            }else {
                weightCalNew = new BigDecimal(Math.ceil(weightCal.doubleValue()));
            }
            fbaBox1.setWeightCalA1(weightCalNew);
            //实际计重=MAX（A1，单票起重）
            weightCalNew = logisticsMmode.getSinglePassCrane().max(weightCalNew);
            //梯度计重单价=(实际计重满足区间的值)
            BigDecimal finalWeightCalNew = weightCalNew;
            tdjzPrice = logisticsMmodeGrads.stream().filter(logisticsMmodeGrads1 -> finalWeightCalNew.compareTo(logisticsMmodeGrads1.getStartSection()) >= 0
                    && finalWeightCalNew.compareTo(logisticsMmodeGrads1.getEndSection()) <= 0).collect(Collectors.toList());
            //抛货系数=(抛重的值-计重的值)
            predVal = (weightVol.subtract(weightCalNew)).setScale(2, BigDecimal.ROUND_HALF_UP);
            //抛货计重单价=(抛货系数满足区间的值)
            BigDecimal finalPredVal = predVal;
            pzjzPrice = logisticsMmodeInfoItems.stream().filter(logisticsMmodeGrads1 -> finalPredVal.compareTo(logisticsMmodeGrads1.getStartSection()) >= 0
                    && finalPredVal.compareTo(logisticsMmodeGrads1.getEndSection()) <= 0).collect(Collectors.toList());
            //计重单价=梯度计重单价+抛重计重单价
            weightPrice = (tdjzPrice.size()!=0?tdjzPrice.get(0).getKg():BigDecimal.ZERO);
            phweightPrice = (tdjzPrice.size()!=0?tdjzPrice.get(0).getKg():BigDecimal.ZERO);

            //实际计重费=(预估计重*计重单价)
            fbaBox1.setPriceTranCalWeightPredict((weightCalNew.multiply(weightPrice)).setScale(2, BigDecimal.ROUND_HALF_UP));
            //超出品名=实际品名-实际免费品名数
            num = gradeNum.size()-logisticsMmode.getNumFreeProName();
            //实际清光费
            fbaBox1.setPriceClearanceOpe(logisticsMmode.getPriceClearanceOpe());
            fbaBox1.setNumProName(gradeNum.size());
        }

        List<LogisticsMmodeCk> logisticsMmodeCkS = new ArrayList<>();
        if (logisticsMmodeCkList.size() != 0){
            logisticsMmodeCkS  = logisticsMmodeCkList.stream().filter(logisticsMmodeCk ->
                    fbaBox1.getDestinationFulfillmentCenterId().equals(logisticsMmodeCk.getWarehouseName())).collect(Collectors.toList());
        }

        if (logisticsMmodeCkS.size() != 0){
            fbaBox1.setWarehouseSurchargePrice(logisticsMmodeCkS.get(0).getWarehouseCost());
        }else {
            fbaBox1.setWarehouseSurchargePrice(BigDecimal.ZERO);
        }
        //仓库附加计重费用 = 仓库附件计重单价*实际计重
        warehouseSurcharge = (weightCalNew.multiply(fbaBox1.getWarehouseSurchargePrice())).setScale(2, BigDecimal.ROUND_HALF_UP);
        fbaBox1.setWarehouseSurcharge(warehouseSurcharge);
        fbaBox1.setPriceTranCalWeightPredict(fbaBox1.getPriceTranCalWeightPredict().add(warehouseSurcharge));

        //实际实重
        fbaBox1.setWeightReal(weightReal);
        //实际抛重
        fbaBox1.setWeightVol(weightVol);
        //装箱计重
        fbaBox1.setWeightCal(weightCalNew);
        //头程箱数
        fbaBox1.setNumBox(fbaBoxDetailListNew.size());
        //抛货系数
        fbaBox1.setJettisonCoe(predVal);
        //梯度计重单价
        fbaBox1.setTdjzPrice(tdjzPrice.size()!=0?tdjzPrice.get(0).getKg():BigDecimal.ZERO);
        //抛货计重单价
        fbaBox1.setPzjzPrice(pzjzPrice.size()!=0?pzjzPrice.get(0).getKg():BigDecimal.ZERO);
        //计重单价
        fbaBox1.setJzPrice(weightPrice);
        //抛货计重费
        fbaBox1.setJettisonWeightCharge(weightVolPredictNew.multiply(phweightPrice).setScale(2, BigDecimal.ROUND_HALF_UP));
        //设置表头附加费材质
        fbaBox1.setPriceQualityExtra(texture);
        //最大附加费材质
        fbaBox1.setSurchargeMaterialMax(surchargeMaterialMax);
        //设置实际材质附加费=材质计费*实际计重
        fbaBox1.setPriceQualityExtraPredict(texture.multiply(weightCalNew).setScale(2, BigDecimal.ROUND_HALF_UP));
        //品名
        fbaBox1.setNumProNameBeyond(num>0?num:0);
        //占比
        fbaBox1.setTradeNamePro(priceClearanceOpePrice);
        //实际品名附加费 = 超出的品名*品名标准
        fbaBox1.setPriceProNameExtraPredict(logisticsMmode.getPriceProNamePerOne().multiply(new BigDecimal(fbaBox1.getNumProNameBeyond())).setScale(2, BigDecimal.ROUND_HALF_UP));
        //实际物流费用 = 实际计重运费+实际材质附加费+实际品名附加费+实际清关费
        fbaBox1.setActualLogisticsFreight(fbaBox1.getPriceTranCalWeightPredict().
                add(fbaBox1.getPriceQualityExtraPredict()).add(fbaBox1.getPriceProNameExtraPredict()
                .add(fbaBox1.getPriceClearanceOpe())));

        //判断是否是抛重发货 -- 进行逻辑计算
        if (fbaBox1.getLoadDelivery().equals("是")){
            //实际抛发清关费=清关费单价
            fbaBox1.setPriceClearanceOpePf(logisticsMmode.getPriceClearanceOpe());
            //抛发实际品名免费数=品名免费数
            fbaBox1.setNumFreeProNamePf(logisticsMmode.getNumFreeProName());
            //抛发超品名数量【=实际品名数-抛发实际品名免费数】
            int numPf = fbaBox1.getNumProName() - fbaBox1.getNumFreeProNamePf();
            numPf = numPf>0?numPf:0;
            //实际抛发品名附加费、费用说明：实际抛发品名附加费=超品名数量*品名附加费单价
            fbaBox1.setPriceProNameExtraPredictPf(logisticsMmode.getPriceProNamePerOne().multiply(new BigDecimal(numPf)).setScale(2, BigDecimal.ROUND_HALF_UP));
            //抛发计重：【=MAX（装箱抛重，单票起重）约分】
            BigDecimal weightCalPf = precision(logisticsMmode.getSinglePassCrane().max(weightVol));
            //实际抛发材质附加费、费用说明：实际抛发材质附加费=MAX（装箱抛重，单票起重）*材质附加单价
            fbaBox1.setPriceQualityExtraPredictPf(weightCalPf.multiply(fbaBox1.getPriceQualityExtra()).setScale(2, BigDecimal.ROUND_HALF_UP));
            //抛发计重单价：【抛发计重对应的梯度价】
            List<LogisticsMmodeGrads> pfLogisticsMmodeGrads;
            BigDecimal pfjzPrice;
            pfLogisticsMmodeGrads = logisticsMmodeGrads.stream().filter(logisticsMmodeGrads1 -> weightCalPf.compareTo(logisticsMmodeGrads1.getStartSection()) >= 0
                    && weightCalPf.compareTo(logisticsMmodeGrads1.getEndSection()) <= 0).collect(Collectors.toList());
            pfjzPrice = (pfLogisticsMmodeGrads.size()!=0?pfLogisticsMmodeGrads.get(0).getKg():BigDecimal.ZERO);
            BigDecimal warehouseSurchargepf = (weightCalPf.multiply(fbaBox1.getWarehouseSurchargePrice())).setScale(2, BigDecimal.ROUND_HALF_UP);
            fbaBox1.setWarehouseSurchargePf(warehouseSurchargepf);
            //实际抛发计重运费、费用说明：实际抛发计重运费=MAX（装箱抛重，单票起重）*抛发计重单价+仓库附加计重费用
            fbaBox1.setPriceTranCalWeightPredictPf(((weightCalPf.multiply(pfjzPrice)).add(warehouseSurchargepf)).setScale(2, BigDecimal.ROUND_HALF_UP));
            //实际抛发物流运费、费用说明：实际抛发物流运费=实际抛发计重运费+实际抛发材质附加费+实际抛发品名附加费+实际抛发清关费
            fbaBox1.setActualLogisticsFreightPf(fbaBox1.getPriceTranCalWeightPredictPf()
                    .add(fbaBox1.getPriceQualityExtraPredictPf())
                    .add(fbaBox1.getPriceProNameExtraPredictPf())
                    .add(fbaBox1.getPriceClearanceOpePf()));
        }

        //删除装箱详情数据
        fbaBoxDetailMapper.deleteCodeBox(fbaBox1.getCode());
        //新增详情数据
        fbaBoxDetailMapper.batchInsert(fbaBoxDetailListNew);

        //        //修改装箱详情
        fbaBoxMapper.updateByGuid(fbaBox1);
//        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        return AjaxResult.success(MessageUtils.message("module.success.issuccess"));
    }


    /**
     *  给对应的箱子赋值
     * @param fbaBoxDetailNew  箱子详情对象
     * @param weight 箱重
     * @param length 长度
     * @param width 宽度
     * @param height 高度
     * @param weightVol  抛重
     * @return
     */
    private FbaBoxDetail valuation(FbaBoxDetail fbaBoxDetailNew, String weight, String length,String width,String height,String weightVol,String price
            ,List<FbaBoxDetail> productInfoList,Integer j){
        fbaBoxDetailNew.setWeight(weight);
        fbaBoxDetailNew.setLength(length);
        fbaBoxDetailNew.setWidth(width);
        fbaBoxDetailNew.setHeight(height);
        fbaBoxDetailNew.setWeightVol(weightVol);
        fbaBoxDetailNew.setPriceSingleBoxReq(new BigDecimal(price));

        String numRealityDeliver = "";
        for (int i = 0; i < productInfoList.size(); i++) {
            switch (j) {
                case 0:
                    numRealityDeliver = productInfoList.get(i).getNumRealityDeliver1();
                    break;
                case 1:
                    numRealityDeliver = productInfoList.get(i).getNumRealityDeliver2();
                    break;
                case 2:
                    numRealityDeliver = productInfoList.get(i).getNumRealityDeliver3();
                    break;
                case 3:
                    numRealityDeliver = productInfoList.get(i).getNumRealityDeliver4();
                    break;
                case 4:
                    numRealityDeliver = productInfoList.get(i).getNumRealityDeliver5();
                    break;
                case 5:
                    numRealityDeliver = productInfoList.get(i).getNumRealityDeliver6();
                    break;
                case 6:
                    numRealityDeliver = productInfoList.get(i).getNumRealityDeliver7();
                    break;
                case 7:
                    numRealityDeliver = productInfoList.get(i).getNumRealityDeliver8();
                    break;
                case 8:
                    numRealityDeliver = productInfoList.get(i).getNumRealityDeliver9();
                    break;
                case 9:
                    numRealityDeliver = productInfoList.get(i).getNumRealityDeliver10();
                    break;
            }
            productInfoList.get(i).setNumRealityDeliver(numRealityDeliver);
            productInfoList.get(i).setNumRealityDeliver1("");
            productInfoList.get(i).setNumRealityDeliver2("");
            productInfoList.get(i).setNumRealityDeliver3("");
            productInfoList.get(i).setNumRealityDeliver4("");
            productInfoList.get(i).setNumRealityDeliver5("");
            productInfoList.get(i).setNumRealityDeliver6("");
            productInfoList.get(i).setNumRealityDeliver7("");
            productInfoList.get(i).setNumRealityDeliver8("");
            productInfoList.get(i).setNumRealityDeliver9("");
            productInfoList.get(i).setNumRealityDeliver10("");
        }
        return fbaBoxDetailNew;
    }

    /**
     *@Description: 审核  —— 添加流程任务、修改流程状态及生效标志
     *@Param: [params] tableDataId 必要参数：单据编码（nid）
     *@return: com.dhecp.common.core.domain.AjaxResult
     *@Author: hlf
     *@date: 2022-05-09 10:11
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public AjaxResult updateFlowGo(Map<String, Object> params) {
        List<FbaBox> fbaBoxList =  JSON.parseArray(params.get("infoItems").toString(), FbaBox.class);
        for (FbaBox item:fbaBoxList
        ) {
            //修改头程装箱状态
            item.setUpdateTime(new Date());
            item.setState(params.get("state").toString());
            item.setAuditTime(new Date());
            item.setAuditUser(ShiroUtils.getUserId());
            fbaBoxMapper.update(item);

            //查询装箱最新数据
            Map<String, Object> params1 = new HashMap<String, Object>();
            params1.put("moduleTable", moduleTable);
            ModuleNidAndBid moduleNidAndBid = moduleNidAndBidMapper.findModuleNidAndBid(params1);    //有事务控制，制单异常不跳过单号

            //新增头程发货订单
            FbaDispatch fbaDispatch = new FbaDispatch();
            fbaDispatch.setGuid(RandomValueUtils.getGUID());
            fbaDispatch.setNid(moduleNidAndBid.getNid());
            fbaDispatch.setBid(moduleNidAndBid.getBid());
            fbaDispatch.setCid(ShiroUtils.getMandatorCid());
            fbaDispatch.setCidName(ShiroUtils.getMandatorCidName());
            fbaDispatch.setbUser(ShiroUtils.getMandatorId());
            fbaDispatch.setbUserName(ShiroUtils.getMandatorName());
            fbaDispatch.setbDept(ShiroUtils.getMandatorDeptPath());
            fbaDispatch.setbDeptName(ShiroUtils.getMandatorDeptName());
            fbaDispatch.setbPosition(ShiroUtils.getMandatorPositionNameDa());
            fbaDispatch.setaUser(ShiroUtils.getUserId());
            fbaDispatch.setaUserName(ShiroUtils.getUserName());
            fbaDispatch.setaDept(ShiroUtils.getUserDeptPath());
            fbaDispatch.setaDeptName(ShiroUtils.getUserDeptName());
            fbaDispatch.setaPosition(ShiroUtils.getUserPositionNameDa());
            fbaDispatch.setCode(moduleNidAndBid.getBid());
            fbaDispatch.setCodePlanOrder(item.getCodeShipment());
            fbaDispatch.setCodeBox(item.getCode());
            fbaDispatch.setCreateTime(new Date());
            fbaDispatch.setEffectStock(true);
            fbaDispatch.setState("0");
            fbaDispatchMapper.insertFbaDispatch(fbaDispatch);
        }
        return AjaxResult.success(MessageUtils.message("module.success.issuccess"));
    }

    /**
     *@Description: 退回  —— 添加流程任务、修改流程状态及生效标志
     *@Param: [params] tableDataId 必要参数：单据编码（nid）
     *@return: com.dhecp.common.core.domain.AjaxResult
     *@Author: hlf
     *@date: 2022-05-09 10:11
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public AjaxResult updateFlowBack(Map<String, Object> params) {
        //修改头程装箱状态
        List<FbaBox> fbaBoxList = fbaBoxMapper.selectByNid(params);
        FbaBox fbaBox = null;
        if (fbaBoxList.size() > 0) {
            fbaBox = fbaBoxList.get(0);
            fbaBox.setState(params.get("state").toString());
            fbaBox.setUpdateTime(new Date());
            fbaBoxMapper.update(fbaBox);
        } else {
            throw new RuntimeException(MessageUtils.message("module.error.lack","头程装箱不存在!"));
        }

        //删除头程发货订单
        FbaDispatch fbaDispatch = new FbaDispatch();
        fbaDispatch.setCodeBox(fbaBox.getCode());
        fbaDispatchMapper.deleteCode(fbaDispatch);
        return AjaxResult.success(MessageUtils.message("module.success.issuccess"));
    }

    /**
     * 修改审核状态
     * @return
     * @author DH-Xxj
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public AjaxResult rollbackState(Map<String, Object> params) {
        List<FbaBox> fbaBoxList =  JSON.parseArray(params.get("infoItems").toString(), FbaBox.class);
        for (FbaBox item:fbaBoxList
        ) {
            //删除对应的箱子详情和箱子
            fbaBoxDetailMapper.delete(item.getCodeShipment());
            fbaBoxMapper.deleteCodeShipment(item);

            //查询装箱单对应的头程计划单修改-未审核状态
            Map<String, Object> params1 = new HashMap<String, Object>();
            params1.put("code",item.getCodeShipment());
            List<FbaPlanOrder> fbaPlanOrderList = fbaPlanOrderMapper.findFbaPlanOrder(params1);
            for (FbaPlanOrder fbaPlanOrder : fbaPlanOrderList){
                fbaPlanOrder.setState("0");
                fbaPlanOrderMapper.update(fbaPlanOrderList.get(0));
            }
        }
        return AjaxResult.success(MessageUtils.message("module.success.issuccess"));
    }

    /**
     * 贴标人装箱人导入
     * @param params
     * @return
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public AjaxResult personnelImport(Map<String, Object> params) {
        if (params.get("infoItems") == null || params.get("infoItems") == "") {
            return AjaxResult.error(MessageUtils.message("module.error.lack.infoItems"));
        }
        List<FbaBox> list = JSON.parseArray(params.get("infoItems").toString(), FbaBox.class);
        FbaBox fbaBox1;
        for (FbaBox fbaBox : list){
            fbaBox1 = fbaBoxMapper.queryFirstByGuid(fbaBox.getGuid());
            if (fbaBox1 == null){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error("头程装箱单不存在,请核实后在操作!");
            }
            //修改装箱贴标人和装箱人
            fbaBox1.setLabelingPerson(String.valueOf(params.get("labelingPerson")));
            fbaBox1.setPackingPerson(String.valueOf(params.get("packingPerson")));
            fbaBoxMapper.updateByGuid(fbaBox1);
        }

        return AjaxResult.success(MessageUtils.message("module.success.issuccess"));
    }

    /**
     * 修改仓库标识
     * @param params
     * @return
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public AjaxResult updateDestinationFulfillmentCenter(Map<String, Object> params) {
        if (params.get("infoItems") == null || params.get("infoItems") == "") {
            return AjaxResult.error(MessageUtils.message("module.error.lack.infoItems"));
        }
        List<FbaBox> list = JSON.parseArray(params.get("infoItems").toString(), FbaBox.class);
        FbaBox fbaBox1;
        for (FbaBox fbaBox : list){
            fbaBox1 = fbaBoxMapper.queryFirstByGuid(fbaBox.getGuid());
            if (fbaBox1 == null){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error("头程装箱单不存在,请核实后在操作!");
            }
            //查询物流方式仓库梯度信息
            Map<String, Object> params11 = new HashMap<String, Object>();
            params11.put("logisticsMmodeGuid",fbaBox1.getLogisticsMmodeGuid());
            List<LogisticsMmodeCk> logisticsMmodeCkList = logsticsMmodeCkMapper.findLogisticsMmodeCk(params11);
            List<LogisticsMmodeCk> logisticsMmodeCkS = new ArrayList<>();
            if (logisticsMmodeCkList.size() != 0){
                logisticsMmodeCkS  = logisticsMmodeCkList.stream().filter(logisticsMmodeCk ->
                        String.valueOf(params.get("destinationFulfillmentCenterId")).equals(logisticsMmodeCk.getWarehouseName())).collect(Collectors.toList());
            }

            if (logisticsMmodeCkS.size() != 0){
                fbaBox1.setWarehouseSurchargePrice(logisticsMmodeCkS.get(0).getWarehouseCost());
            }else {
                fbaBox1.setWarehouseSurchargePrice(BigDecimal.ZERO);
            }
            BigDecimal warehouseSurcharge = (fbaBox1.getWeightCal().multiply(fbaBox1.getWarehouseSurchargePrice())).setScale(2, BigDecimal.ROUND_HALF_UP);
            //先减去之前增加的仓库附加费
            fbaBox1.setPriceTranCalWeightPredict(fbaBox1.getPriceTranCalWeightPredict().subtract(fbaBox1.getWarehouseSurcharge()));
            fbaBox1.setActualLogisticsFreight(fbaBox1.getActualLogisticsFreight().subtract(fbaBox1.getWarehouseSurcharge()));
            //在添加新的仓库附加费
            fbaBox1.setPriceTranCalWeightPredict(fbaBox1.getPriceTranCalWeightPredict().add(warehouseSurcharge));
            fbaBox1.setActualLogisticsFreight(fbaBox1.getActualLogisticsFreight().add(warehouseSurcharge));
            if (fbaBox1.getLoadDelivery().equals("是")){
                BigDecimal weightCalPf = precision(fbaBox1.getSinglePassCrane().max(fbaBox1.getWeightVol()));
                BigDecimal warehouseSurchargepf = (weightCalPf.multiply(fbaBox1.getWarehouseSurchargePrice())).setScale(2, BigDecimal.ROUND_HALF_UP);
                fbaBox1.setPriceTranCalWeightPredictPf(fbaBox1.getPriceTranCalWeightPredictPf().subtract(fbaBox1.getWarehouseSurchargePf()));
                fbaBox1.setActualLogisticsFreightPf(fbaBox1.getActualLogisticsFreightPf().subtract(fbaBox1.getWarehouseSurchargePf()));
                fbaBox1.setPriceTranCalWeightPredictPf(fbaBox1.getPriceTranCalWeightPredictPf().add(warehouseSurchargepf));
                fbaBox1.setActualLogisticsFreightPf(fbaBox1.getActualLogisticsFreightPf().add(warehouseSurchargepf));
                fbaBox1.setWarehouseSurchargePf(warehouseSurchargepf);
            }
            fbaBox1.setWarehouseSurcharge(warehouseSurcharge);

            //修改仓库标识
            fbaBox1.setDestinationFulfillmentCenterId(String.valueOf(params.get("destinationFulfillmentCenterId")));
            fbaBoxMapper.updateByGuid(fbaBox1);
        }

        return AjaxResult.success(MessageUtils.message("module.success.issuccess"));
    }

    /**
     * 标记发货
     * @param params
     * @return
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public AjaxResult isShipments(Map<String, Object> params) {
        if (params.get("infoItems") == null || params.get("infoItems") == "") {
            return AjaxResult.error(MessageUtils.message("module.error.lack.infoItems"));
        }
        List<FbaBox> list = JSON.parseArray(params.get("infoItems").toString(), FbaBox.class);
        FbaBox fbaBox1;
        for (FbaBox fbaBox : list){
            fbaBox1 = fbaBoxMapper.queryFirstByGuid(fbaBox.getGuid());
            if (fbaBox1 == null){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error("头程装箱单不存在,请核实后在操作!");
            }
            if (!fbaBox1.getStateTrack().equals("1")){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error("选择单据中未审核,请核实后在操作!");
            }
            if (fbaBox1.getStateTrack().equals("4")){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error("选择单据中有物流已发货,无需再次操作!");
            }
            //修改标记发货
            fbaBox1.setStateTrack("4");
            fbaBox1.setStateTrackName("物流已发货");
            fbaBox1.setDeliveryTime(new Date());
            fbaBox1.setDeliveryUser(ShiroUtils.getMandatorId());
            fbaBoxMapper.updateByGuid(fbaBox1);
        }

        return AjaxResult.success(MessageUtils.message("module.success.issuccess"));
    }

    /**
     * 完成单审核
     * @param params
     * @return
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public AjaxResult zxwcShbtn(Map<String, Object> params) {
        if (params.get("infoItems") == null || params.get("infoItems") == "") {
            return AjaxResult.error(MessageUtils.message("module.error.lack.infoItems"));
        }
        List<FbaBox> list = JSON.parseArray(params.get("infoItems").toString(), FbaBox.class);
        FbaBox fbaBox1;
        List<FbaBox> fbaBox1ListNew = new ArrayList<>();
        FbaSpellTicket fbaSpellTicket;
        List<FbaSpellTicket> fbaSpellTicketList = new ArrayList<>();
        Map<String, Object> params2;
        List<FbaBoxDetail> fbaBoxDetaiList;
        FbaSpellTicketDetail fbaSpellTicketDetail;
        List<FbaSpellTicketDetail> fbaSpellTicketDetailList = new ArrayList<>();
        for (FbaBox fbaBox : list){
            fbaBox1 = fbaBoxMapper.queryFirstByGuid(fbaBox.getGuid());
            if (fbaBox1 == null){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error("头程装箱单不存在,请核实后在操作!");
            }
            if (!fbaBox1.getStatePrint().equals("5")){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error("选择单据中箱标已打印状态,请核实后在操作!");
            }
            if (!fbaBox1.getStateTrack().equals("0")){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error("选择单据中物流状态不是无,请核实后在操作!");
            }
            fbaBox1.setStateTrack("1");
            fbaBox1.setStateTrackName("已交付物流部");
            fbaBox1ListNew.add(fbaBox1);

            //新增拼票数据
            fbaSpellTicket = new FbaSpellTicket();
            fbaSpellTicket.setGuid(RandomValueUtils.getGUID());
            fbaSpellTicket.setCid(ShiroUtils.getMandatorCid());
            fbaSpellTicket.setCidName(ShiroUtils.getMandatorCidName());
            fbaSpellTicket.setbUser(ShiroUtils.getMandatorId());
            fbaSpellTicket.setbUserName(ShiroUtils.getMandatorName());
            fbaSpellTicket.setbDept(ShiroUtils.getMandatorDeptPath());
            fbaSpellTicket.setbDeptName(ShiroUtils.getMandatorDeptName());
            fbaSpellTicket.setbPosition(ShiroUtils.getMandatorPositionNameDa());
            fbaSpellTicket.setaUser(ShiroUtils.getUserId());
            fbaSpellTicket.setaUserName(ShiroUtils.getUserName());
            fbaSpellTicket.setaDept(ShiroUtils.getUserDeptPath());
            fbaSpellTicket.setaDeptName(ShiroUtils.getUserDeptName());
            fbaSpellTicket.setaPosition(ShiroUtils.getUserPositionNameDa());
            fbaSpellTicket.setSpellTicketState("0");
            BeanUtils.copyProperties(fbaBox1,fbaSpellTicket);
            fbaSpellTicket.setCreateUser(ShiroUtils.getUserId());
            fbaSpellTicket.setCreateTime(new Date());
            fbaSpellTicketList.add(fbaSpellTicket);

            //拼票详情
            params2 = new HashMap<String, Object>();
            params2.put("codeBox",fbaBox1.getCode());
            fbaBoxDetaiList = fbaBoxDetailMapper.findFbaBoxDetail(params2);
            for (FbaBoxDetail fbaBoxDetail :fbaBoxDetaiList){
                fbaSpellTicketDetail = new FbaSpellTicketDetail();
                fbaSpellTicketDetail.setGuid(RandomValueUtils.getGUID());
                fbaSpellTicketDetail.setFbaSpellTicketGuid(fbaSpellTicket.getGuid());
                BeanUtils.copyProperties(fbaBoxDetail,fbaSpellTicketDetail);
                fbaSpellTicketDetailList.add(fbaSpellTicketDetail);
            }
        }

        if (fbaSpellTicketList.size() != 0 ){
            fbaSpellTickMapper.batchInsert(fbaSpellTicketList);
        }

        if (fbaSpellTicketDetailList.size() != 0 ){
            fbaSpellTicketDetailMapper.batchInsert(fbaSpellTicketDetailList);
        }

        if (fbaBox1ListNew.size() != 0){
            fbaBoxMapper.updateBatchGuid(fbaBox1ListNew);
        }

        return AjaxResult.success(MessageUtils.message("module.success.issuccess"));
    }

    /**
     * ex表格导入多个FBA设置状态为标记发货
     * @return
     * @author DH-Xxj
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public AjaxResult batchDelivery(Map<String, Object> params) {
        JSONArray jsonArray = JSON.parseArray(params.get("infoItems").toString());
        List<FbaBox> fbaBoxList = new ArrayList<>();
        FbaBox fbaBox;
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = (JSONObject) jsonArray.get(i);
            fbaBox = new FbaBox();
            fbaBox.setShipmentId(jsonObject.get("shipmentId").toString());
            fbaBoxList.add(fbaBox);
        }
        //根据fba查询完成单信息
        List<FbaBox> fbaBoxShipmentList = fbaBoxMapper.findFbaBoxShipment(fbaBoxList);

        //筛选满足物流状态为发票清单已打印
        List<FbaBox> fbaBoxPrintedList = fbaBoxShipmentList.stream().filter(fbaBox1 -> "1".equals(fbaBox1.getStateTrack()))
                .collect(Collectors.toList());
        for (FbaBox fbaBox1 : fbaBoxPrintedList){
            fbaBox1.setStateTrack("4");
            fbaBox1.setStateTrackName("物流已发货");
            fbaBox1.setDeliveryTime(new Date());
            fbaBox1.setDeliveryUser(ShiroUtils.getMandatorId());
        }
        //筛选出不符合修改的fba数据
        List<FbaBox> collect = new ArrayList<>();
        for (FbaBox fbaBox1 : fbaBoxList){
            List<FbaBox> existList = fbaBoxPrintedList.stream().filter(fbaBox3 -> fbaBox3.getShipmentId().equals(fbaBox1.getShipmentId()))
                    .collect(Collectors.toList());
            if (existList.size() == 0){
                collect.add(fbaBox1);
            }
        }

        int updateLength = fbaBoxPrintedList.size();
        int i = 0;
        while (updateLength > 90) {
            //修改满足的完成单信息数据为已发货
            fbaBoxMapper.updateBatchGuid(fbaBoxPrintedList);
            i = i + 90;
            updateLength = updateLength - 90;
        }
        if (updateLength > 0) {
            fbaBoxMapper.updateBatchGuid(fbaBoxPrintedList);
        }

        //将修改的提示出来
        if (collect.size() > 0){
//            List<String> result = collect.stream()
//                    .map(item -> item.getShipmentId())
//                    .collect(Collectors.toList());
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            return AjaxResult.error("导入的数据中FBA编号:"+StringUtils.strip(result.toString(),"[]")+
            //        params.put("moduleTable", moduleTableS);
//        params.put("entity", new FbaBox());

            params.put("getFieldAttributesType", "export");
            List<SysDictionaryForExport> fieldList = new ArrayList<>();
            SysDictionaryForExport sysDictionaryForExport = new SysDictionaryForExport();
            sysDictionaryForExport.setGuid(RandomValueUtils.getGUID());
            sysDictionaryForExport.setModuleTable(moduleTableFH);
            sysDictionaryForExport.setFieldName("FBA编号");
            sysDictionaryForExport.setFields("shipmentId");
            sysDictionaryForExport.setFieldFrontType("t_test");
            sysDictionaryForExport.setFieldFrontTemplet("t_test");
            sysDictionaryForExport.setFieldFrontOrder(1);
            fieldList.add(sysDictionaryForExport);
            ExportExcelUtils<FbaBox> util = new ExportExcelUtils<FbaBox>("TP_FBABOXS", new FbaBox());
            AjaxResult ajaxResult = util.exportExcel(collect, fieldList, "标记发货错误数据", "export");
            return new AjaxResult(400,"批量标记发货部分失败,具体请看标记发货错误数据表格!",ajaxResult.get("msg"));
        }
        return AjaxResult.success("批量标记发货成功");
    }

    /**
     * 导入并直接回填追踪编号单据
     * @return
     * @author DH-Xxj
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public AjaxResult importData(Map<String, Object> params) {
        JSONArray jsonArray = JSON.parseArray(params.get("infoItems").toString());
        Map<String, List<String>> params1 = new HashMap<String, List<String>>();
        List<String> stateTrackCodeList;
        String shipmentId = "";
        String stateTrackCode = "";
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = (JSONObject) jsonArray.get(i);
            if (jsonObject.get("shipmentId") != null){
                shipmentId = jsonObject.get("shipmentId").toString();
                stateTrackCode = jsonObject.get("stateTrackCode").toString();
                if (shipmentId.indexOf("FBA") == -1){
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return AjaxResult.error("导入数据出错");
                } else {
                    if (params1.get(shipmentId) == null){
                        stateTrackCodeList = new ArrayList<>();
                        stateTrackCodeList.add(stateTrackCode);
                        params1.put(shipmentId,stateTrackCodeList);
                    } else {
                        stateTrackCodeList = params1.get(shipmentId);
                        stateTrackCodeList.add(stateTrackCode);
                        params1.put(shipmentId,stateTrackCodeList);
                    }
                }
            }
        }

        FbaBox fbaBox;
        List<FbaBoxDetail> fbaBoxDetailList;
        for (Map.Entry<String,List<String>> entry: params1.entrySet()) {
            //查询装箱单是否箱数符合上传追踪编号数据
            fbaBox = fbaBoxMapper.queryFirstByShipmentId(entry.getKey());
            if (fbaBox == null){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error("FBA编号:"+entry.getKey()+"数据不存在,请核实后再操作!");
            }
            if (fbaBox.getNumBox() != entry.getValue().size()){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error("FBA编号:"+entry.getKey()+"数据头程箱数与上传数据追踪编号数据不匹配,请核实后再操作!");
            }
            Map<String, Object> params2 = new HashMap<String, Object>();
            params2.put("codeBox",fbaBox.getCode());
            fbaBoxDetailList = fbaBoxDetailMapper.findFbaBoxDetail(params2);
            if (fbaBoxDetailList.size() != entry.getValue().size()){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error("FBA编号:"+entry.getKey()+"数据头程箱数与上传数据追踪编号数据不匹配,请核实后再操作!");
            }
            for (int i = 0; i < fbaBoxDetailList.size(); i++) {
                if (entry.getValue().get(i).equals("") || entry.getValue().get(i) == null){
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return AjaxResult.error("FBA编号:"+fbaBox.getShipmentId()+"追踪编号为空,请核实后再操作!");
                }

                fbaBoxDetailList.get(i).setTrackingCode(entry.getValue().get(i));
                fbaBoxDetailMapper.updateByGuid(fbaBoxDetailList.get(i));
            }
//            if (fbaBox.getStateTrack().equals("2")){
//                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//                return AjaxResult.error("FBA编号:"+fbaBox.getShipmentId()+"追踪编号已导入,请核实后再操作!");
//            }
            if (!fbaBox.getStateTrack().equals("2")){
                if (fbaBox.getStateTrack().equals("1")  || fbaBox.getStateTrack().equals("0")){
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return AjaxResult.error("FBA编号:"+fbaBox.getShipmentId()+"物流未发货,请核实后再操作!");
                }
            }

            //修改物流状态为追踪编号已导入
            if (fbaBox.getStateTrack().equals("4")){
                fbaBox.setTrackingTime(new Date());
                fbaBox.setStateTrack("2");
                fbaBox.setStateTrackName("追踪编号已导入");
            }
            fbaBoxMapper.update(fbaBox);
        }
        return AjaxResult.success(MessageUtils.message("module.success.issuccess"));
    }

    /**
     *@Description: 审核  —— 添加流程任务、修改流程状态及生效标志
     *@Param: [params] tableDataId 必要参数：单据编码（nid）
     *@return: com.dhecp.common.core.domain.AjaxResult
     *@Author: hlf
     *@date: 2022-05-09 10:11
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public AjaxResult printList(Map<String, Object> params) {
        params.put("moduleTable", "TP_ListInvoices");
        params.put("entity", new FbaBox());

        //获取标题
        List<SysDictionaryForExport> fieldList = dictionaryForFieldService.queryExportFieldList(params);
        List<FbaBox> fbaBoxList =  JSON.parseArray(params.get("infoItems").toString(), FbaBox.class);
        if (fbaBoxList.size() == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error("头程装箱单数据不存在!");
        }
        List<FbaBox> fbaBox1List = fbaBoxMapper.findFbaBoxBatch(fbaBoxList);
        if (fbaBoxList.size() != fbaBox1List.size()){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error("选择的头程装箱单不存在,请核实后在操作!");
        }
        List<PrintList2> printBatchList = fbaBoxMapper.printListBatchGuid(fbaBoxList);

        List<FbaBoxDetail> fbaBoxDetailBatchList  = fbaBoxDetailMapper.fbaBoxDetailBatchList(fbaBoxList);

        Set<String> productBases = new HashSet<>();
        List<FbaBoxDetail> fbaBoxDetailListnew;
        for (FbaBoxDetail fbaBoxDetail : fbaBoxDetailBatchList) {
            //获取商品信息
            fbaBoxDetailListnew = JSON.parseArray(fbaBoxDetail.getProductInfo(), FbaBoxDetail.class);
            for (FbaBoxDetail fbaBoxDetai : fbaBoxDetailListnew) {
                productBases.add(fbaBoxDetai.getCommodityCode());
            }
        }
        List<ProductBasis> productActiveBatchList  = productBasisMapper.findOnlineStoreProductsBatch(productBases);

        List<PrintList2> printList;
        PrintList2 printList2;
        List<ProductBasis> productActiveList = null;
        List<FbaBoxDetail> fbaBoxDetailList;
        ProductBasis productActive = null;
        PrintList2 printList3;
        List<PrintList2> printList2s = new ArrayList<>();
        String filename = null;
        for (FbaBox fbaBox : fbaBox1List) {
            //装箱数据
            printList = printBatchList.stream().filter(print -> print.getGuid().equals(fbaBox.getGuid()))
                    .collect(Collectors.toList());
            if (printList.size() == 0) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error("头程装箱:" + fbaBox.getCode() + "不存在!");
            }
            printList2 = printList.get(0);

            //头程计划单下所有箱子数据
            fbaBoxDetailList = fbaBoxDetailBatchList.stream().filter(fbaBoxDetail -> fbaBoxDetail.getCodeBox().equals(fbaBox.getCode()))
                    .collect(Collectors.toList());
            if (fbaBoxDetailList.size() == 0) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error("箱子数据不存在!");
            }

            int beginNum = 1;
            int endNum = 0;
            for (FbaBoxDetail fbaBoxDetail11 : fbaBoxDetailList) {
                beginNum += 1;
                //获取商品信息
                fbaBoxDetailListnew = JSON.parseArray(fbaBoxDetail11.getProductInfo(), FbaBoxDetail.class);
                //进行排序（naturalOrder 正序）（reverseOrder倒叙）
                fbaBoxDetailListnew = fbaBoxDetailListnew.stream().
                        sorted(Comparator.comparing(FbaBoxDetail::getCommodityCode, Comparator.naturalOrder())).
                        collect(Collectors.toList());
                endNum = beginNum + fbaBoxDetailListnew.size() - 1;
                for (FbaBoxDetail fbaBoxDetail : fbaBoxDetailListnew) {
                    productActiveList = productActiveBatchList.stream().filter(productBasis -> productBasis.getCode().equals(fbaBoxDetail.getCommodityCode()))
                            .collect(Collectors.toList());
                    if (productActiveList.size() == 0) {
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        return AjaxResult.error("商品库信息不存在!");
                    }
//                    if (productActiveList.size() > 1) {
//                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//                        return AjaxResult.error("商品库信息大于2条数据错误,请联系管理员!");
//                    }
                    productActive = productActiveList.get(0);
                    printList3 = new PrintList2();
                    BeanUtils.copyProperties(printList2, printList3);

                    if (printList2.getDestinationFulfillmentCente() == null) {
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        return AjaxResult.error("亚马逊地址不存在,请维护后导出!");
                    }
                    ArrayList<String> arrayList = new ArrayList<String>();
                    arrayList.add(printList2.getName1());
                    arrayList.add(printList2.getAddressLine11());
                    arrayList.add(printList2.getCity1() + "," + printList2.getStateOrProvinceCode1() + " " + printList2.getPostalCode1());
                    arrayList.add(printList2.getCountryCode1() + " (" + printList2.getDestinationFulfillmentCente() + ")");
                    String content = String.join("\n", arrayList);
                    printList3.setHarvestAddress(content);

                    arrayList = new ArrayList<String>();
                    arrayList.add(printList2.getName());
                    arrayList.add(printList2.getAddressLine1());
                    arrayList.add(printList2.getAddressLine2());
                    arrayList.add(printList2.getCity() + "," + printList2.getStateOrProvinceCode() + " " + printList2.getPostalCode());
                    arrayList.add("CN");
//                    arrayList.add(printList2.getCountryCode());
                    content = String.join("\n", arrayList);
                    printList3.setShipAddress(content);

                    printList3.setBeginNum(beginNum);
                    printList3.setEndNum(endNum);
                    printList3.setContainerNo(fbaBox.getShipmentId() + "U00000" + (fbaBoxDetail11.getBoxIndex() + 1));
                    printList3.setLength(fbaBoxDetail11.getLength());
                    printList3.setWidth(fbaBoxDetail11.getWidth());
                    printList3.setHeight(fbaBoxDetail11.getHeight());
                    printList3.setWeight(fbaBoxDetail11.getWeight());
                    printList3.setWeightVol(fbaBoxDetail11.getWeightVol());
                    printList3.setIndexDumping(Double.valueOf(fbaBoxDetail11.getWeightVol()) - Double.valueOf(fbaBoxDetail11.getWeight()));
                    printList3.setBrand("N/A");
                    printList3.setModel(productActive.getCode());
                    printList3.setProductPicture(productActive.getImg());
                    printList3.setNameCn(productActive.getNameCn());
                    printList3.setNameEn(productActive.getNameEn());
                    printList3.setCodeHs(productActive.getCodeHs());
                    printList3.setMaterialCn(productActive.getMaterialCn());
                    printList3.setMaterialEn(productActive.getMaterialEn());
                    printList3.setUsageCn(productActive.getUsageCn());
                    printList3.setUsageEn(productActive.getUsageEn());
                    if(productActive.getSizeWeight() != null){
                        printList3.setSizeWeight(Double.valueOf(String.format("%.3f", productActive.getSizeWeight()/1000)));
                    }
                    printList3.setPriceIn(Double.valueOf(fbaBoxDetail.getPriceIn()));
                    printList3.setNameUnit(productActive.getNameUnit());
                    printList3.setLinkJP(fbaBoxDetail.getLinkJP());
                    printList3.setIsSign(fbaBoxDetail.getIsSign());
                    printList3.setNumPlanDeliver(fbaBoxDetail.getNumRealityDeliver());
                    if (!printList3.getNumPlanDeliver().equals("0") && !printList3.getNumPlanDeliver().equals("")){
                        printList2s.add(printList3);
                    }
                }
                beginNum = endNum;
            }
        }
        OutputStream out = null;
        HSSFWorkbook wb = null;
        try {
            //创建HSSFWorkbook对象
            wb = new HSSFWorkbook();
            //建立sheet对象
            HSSFSheet sheet = wb.createSheet("发票清单表");
            //在sheet里创建第一行，参数为行索引
            HSSFRow row1 = sheet.createRow(0);
            HSSFCell cell;
            HSSFCellStyle firstStyle = null;
            HSSFFont firstFont = null;
            for (int i = 0; i < fieldList.size(); i++) {
                //创建单元格
                cell = row1.createCell(i);
                //设置单元格内容
                cell.setCellValue(fieldList.get(i).getFieldName());
                if (i == 0){
                    firstStyle = wb.createCellStyle();
                    firstFont = wb.createFont();
                    addHSSFWorkbook(firstStyle,firstFont,wb, cell, 2, "宋体", false, (short) 11,false);
                } else {
                    addHSSFWorkbook(firstStyle,firstFont,wb, cell, 2, "宋体", false, (short) 11,false);
                }
                sheet.setColumnWidth(i, 100 * 48);
            }
            HSSFRow row2;
            for (int i = 0; i < printList2s.size(); i++) {
                //采购合计
                String purchasePrice = "";
                String weightTol = "";
                for (int k = printList2s.get(i).getBeginNum(); k <= printList2s.get(i).getEndNum(); k++) {
                    if (k==printList2s.get(i).getBeginNum()){
                        purchasePrice = "AL"+k+"*"+"AO"+k;
                        weightTol = "AK"+k+"*"+"AO"+k;
                    }else {
                        purchasePrice = purchasePrice + "+" +"AL"+k+"*"+"AO"+k;
                        weightTol = weightTol + "+" +"AK"+k+"*"+"AO"+k;
                    }
                }
                row2 = sheet.createRow(i+1);
                for (int j = 0; j < fieldList.size(); j++) {
                    //创建单元格
                    cell = row2.createCell(j);
                    //设置单元格内容
                    if (fieldList.get(j).getFields().equals("code")){
                        cell.setCellValue(printList2s.get(i).getCode());
                    } else if (fieldList.get(j).getFields().equals("fpoUserName")){
                        cell.setCellValue(printList2s.get(i).getFpoUserName());
                    }else if (fieldList.get(j).getFields().equals("nameLogsticsPattern")){
                        cell.setCellValue(printList2s.get(i).getNameLogsticsPattern());
                    }else if (fieldList.get(j).getFields().equals("nameLogsticsWay")){
                        cell.setCellValue(printList2s.get(i).getNameLogsticsWay());
                    }else if (fieldList.get(j).getFields().equals("nameLogsticsClearance")){
                        cell.setCellValue(printList2s.get(i).getNameLogsticsClearance());
                    }else if (fieldList.get(j).getFields().equals("vGsMc")){
                        cell.setCellValue(printList2s.get(i).getVGsMc());
                    }else if (fieldList.get(j).getFields().equals("vGsJc")){
                        cell.setCellValue(printList2s.get(i).getVGsJc());
                    }else if (fieldList.get(j).getFields().equals("Phone")){
                        if(isNumber(printList2s.get(i).getPhone())){
                            cell.setCellValue(Double.valueOf(printList2s.get(i).getPhone()));
                        } else{
                            cell.setCellValue(printList2s.get(i).getPhone());
                        }
                    }else if (fieldList.get(j).getFields().equals("ShipAddress")){
                        cell.setCellValue(printList2s.get(i).getShipAddress());
                    }else if (fieldList.get(j).getFields().equals("HarvestAddress")){
                        cell.setCellValue(printList2s.get(i).getHarvestAddress());
                    }else if (fieldList.get(j).getFields().equals("VAT")){
                        cell.setCellValue(printList2s.get(i).getVAT());
                    }else if (fieldList.get(j).getFields().equals("EORI")){
                        cell.setCellValue(printList2s.get(i).getEORI());
                    }else if (fieldList.get(j).getFields().equals("destinationFulfillmentCenterId")){
                        cell.setCellValue(printList2s.get(i).getDestinationFulfillmentCente());
                    }else if (fieldList.get(j).getFields().equals("shipmentId")){
                        cell.setCellValue(printList2s.get(i).getShipmentId());
                    }else if (fieldList.get(j).getFields().equals("trackingCode")){
                        cell.setCellValue(printList2s.get(i).getTrackingCode());
                    }else if (fieldList.get(j).getFields().equals("numBox")){
                        cell.setCellValue(Double.valueOf(printList2s.get(i).getNumBox()));
                    }else if (fieldList.get(j).getFields().equals("ContainerNo")){
                        cell.setCellValue(printList2s.get(i).getContainerNo());
                    }else if (fieldList.get(j).getFields().equals("Length")){
                        cell.setCellValue(Double.valueOf(printList2s.get(i).getLength()));
                    }else if (fieldList.get(j).getFields().equals("Width")){
                        cell.setCellValue(Double.valueOf(printList2s.get(i).getWidth()));
                    }else if (fieldList.get(j).getFields().equals("Height")){
                        cell.setCellValue(Double.valueOf(printList2s.get(i).getHeight()));
                    }else if (fieldList.get(j).getFields().equals("weightVol")){
                        cell.setCellValue(Double.valueOf(printList2s.get(i).getWeightVol()));
                    }else if (fieldList.get(j).getFields().equals("Weight")){
                        cell.setCellValue(Double.valueOf(printList2s.get(i).getWeight()));
                    }else if (fieldList.get(j).getFields().equals("IndexDumping")){
                        cell.setCellFormula("T"+(i+2)+"-"+"U"+(i+2));
                    }else if (fieldList.get(j).getFields().equals("PurchasePrice")){
                        cell.setCellFormula("ROUND("+purchasePrice+",2)");
                    }else if (fieldList.get(j).getFields().equals("PurchasePrice1")){
                        cell.setCellFormula("ROUND(("+purchasePrice+")" + "/9,2)");
                    }else if (fieldList.get(j).getFields().equals("PurchasePrice2")){
                        cell.setCellFormula("ROUND(("+purchasePrice+")"+"/6.4,2)");
                    }else if (fieldList.get(j).getFields().equals("TotalWeight")){
                        cell.setCellFormula("ROUND("+weightTol+",2)");
                    }else if (fieldList.get(j).getFields().equals("Brand")){
                        cell.setCellValue("N/A");
                    }else if (fieldList.get(j).getFields().equals("Model")){
                        cell.setCellValue(printList2s.get(i).getModel());
                    }else if (fieldList.get(j).getFields().equals("ProductPicture")){
                        try {
//                            addPhotograph(sheet,wb,printList2s.get(i).getProductPicture(),i+1);
                        }catch (Exception e){
                            if (e.getMessage().equals("Can't get input stream from URL!")){
                                cell.setCellValue("");
                            }
                        }
                    }else if (fieldList.get(j).getFields().equals("nameCn")){
                        cell.setCellValue(printList2s.get(i).getNameCn());
                    }else if (fieldList.get(j).getFields().equals("nameEn")){
                        cell.setCellValue(printList2s.get(i).getNameEn());
                    }else if (fieldList.get(j).getFields().equals("codeHs")){
                        if(isNumber(printList2s.get(i).getCodeHs())){
                            cell.setCellValue(Double.valueOf(printList2s.get(i).getCodeHs()));
                        } else{
                            cell.setCellValue(printList2s.get(i).getCodeHs());
                        }
                    }else if (fieldList.get(j).getFields().equals("materialCn")){
                        cell.setCellValue(printList2s.get(i).getMaterialCn());
                    }else if (fieldList.get(j).getFields().equals("materialEn")){
                        cell.setCellValue(printList2s.get(i).getMaterialEn());
                    }else if (fieldList.get(j).getFields().equals("usageCn")){
                        cell.setCellValue(printList2s.get(i).getUsageCn());
                    }else if (fieldList.get(j).getFields().equals("usageEn")){
                        cell.setCellValue(printList2s.get(i).getUsageEn());
                    }else if (fieldList.get(j).getFields().equals("sizeWeight")){
                        if (printList2s.get(i).getSizeWeight() != null){
                            cell.setCellValue(Double.valueOf(printList2s.get(i).getSizeWeight()));
                        }
                    }else if (fieldList.get(j).getFields().equals("priceIn")){
                        if (printList2s.get(i).getPriceIn() != null){
                            cell.setCellValue(Double.valueOf(printList2s.get(i).getPriceIn()));
                        }
                    }else if (fieldList.get(j).getFields().equals("nameUnit")){
                        cell.setCellValue(printList2s.get(i).getNameUnit());
                    }else if (fieldList.get(j).getFields().equals("linkJP")){
                        cell.setCellValue(printList2s.get(i).getLinkJP());
                    }else if (fieldList.get(j).getFields().equals("numPlanDeliver")){
                        if (printList2s.get(i).getNumPlanDeliver() != null){
                            cell.setCellValue(Double.valueOf(printList2s.get(i).getNumPlanDeliver().equals("")?"0":printList2s.get(i).getNumPlanDeliver()));
                        }
                    }else if (fieldList.get(j).getFields().equals("IsSign")){
                        cell.setCellValue(printList2s.get(i).getIsSign());
                    }
                    if (i == 0){
                        firstStyle = wb.createCellStyle();
                        firstFont = wb.createFont();
                        addHSSFWorkbook(firstStyle,firstFont,wb, cell, 1, "宋体", false, (short) 11, false);
                    } else {
                        addHSSFWorkbook(firstStyle,firstFont,wb, cell, 1, "宋体", false, (short) 11, false);
                    }

                }
            }



            filename = UUID.randomUUID().toString() + "_" + "发票清单" + ".xlsx";
            String downloadPath = Global.getDownloadPath() + filename;
            File desc = new File(downloadPath);
            if (!desc.getParentFile().exists())
            {
                desc.getParentFile().mkdirs();
            }
            out = new FileOutputStream(downloadPath);
//                out = new FileOutputStream("C:/Users/Administrator/Desktop" + "/" + 1 + ".xlsx");
            wb.write(out);
//                out.close();

            return AjaxResult.success(filename);
        }catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error("导出发票清单失败!");
        }
        finally{
            if (wb != null){
                try{
                    wb.close();
                }
                catch (IOException e1){
                    e1.printStackTrace();
                }
            }
            if (out != null){
                try{
                    out.close();
                }
                catch (IOException e1){
                    e1.printStackTrace();
                }
            }
        }

    }


    /**
     * 添加图片
     * @return
     */
    private void  addPhotograph(HSSFSheet sheet ,HSSFWorkbook wb,String urls,Integer i) throws Exception{
        //给标题插入图片
        ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
//        URL url = new URL("http://cdn.mini-ease.com/profile/images/20230110/fa57b92248dbf21b479e7efd2cd25298.jpg");
        URL url = new URL(urls);
        BufferedImage bi = ImageIO.read(url);
        if (bi != null) {

            //获取长宽
//        Integer width = bi.getWidth();
//        Integer height = bi.getHeight();
            // 将图片写入流中
            ImageIO.write(bi, "png", byteArrayOut);
            // 利用HSSFPatriarch将图片写入EXCEL
            HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
            /**
             * 该构造函数有8个参数
             * int dx1, int dy1, int dx2, int dy2,
             * short col1, int row1, short col2, int row2
             * excel中的cellNum和rowNum的index都是从0开始的
             */
            //图片一导出到单元格中
            HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 0, 0,
                    (short) 28, i, (short) 29, i + 1);
            // 插入图片
            patriarch.createPicture(anchor, wb.addPicture(byteArrayOut
                    .toByteArray(), HSSFWorkbook.PICTURE_TYPE_PNG));
        }
    }



    private HSSFCellStyle addHSSFWorkbook(HSSFCellStyle firstStyle,HSSFFont firstFont,HSSFWorkbook wb, HSSFCell cell,Integer alignment,String fontName,boolean bold,short fontHeightInPoints,boolean wrapText){
        if (alignment == 1){
            firstStyle.setAlignment(HorizontalAlignment.CENTER); // 创建一个居中格式
            firstStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直居中
        } else if (alignment == 2){
            firstStyle.setAlignment(HorizontalAlignment.CENTER); // 创建一个居中格式
            firstStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直居中
            firstStyle.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex());	//更改背景颜色
            firstStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        }

        addHSSFCellStyle(firstStyle);

        firstFont.setFontName(fontName);
        firstFont.setBold(bold);
        firstFont.setFontHeightInPoints(fontHeightInPoints);
        if (alignment == 2){
            firstFont.setColor(IndexedColors.WHITE.getIndex());
        }
        firstStyle.setFont(firstFont);
        firstStyle.setWrapText(wrapText); //设置换行
        cell.setCellStyle(firstStyle);
        return firstStyle;
    }


    private HSSFCellStyle addHSSFCellStyle(HSSFCellStyle firstStyle){
        firstStyle.setBorderRight(BorderStyle.THIN);	//设置单元格右边框的边框类型
        firstStyle.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());	//设置右边边框的颜色
        firstStyle.setBorderLeft(BorderStyle.THIN);	//设置单元格左边框的边框类型
        firstStyle.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());	//设置左边框的颜色
        firstStyle.setBorderTop(BorderStyle.THIN);	//设置单元格上边框使用的边框类型
        firstStyle.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());	//设置上边框的颜色
        firstStyle.setBorderBottom(BorderStyle.THIN);	//设置单元格下边框使用的边框类型
        firstStyle.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());	//设置下边框的颜色
        return firstStyle;
    }

    private  boolean isNumber(String str) {

        if (StringUtils.isNotEmpty(str)) {
            String reg = "^[0-9]+(.[0-9]+)?$";
            return str.matches(reg);
        }
        return false;
    }

    /**
     * 是否是自税
     * @param params
     * @return
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public AjaxResult selfTax(Map<String, Object> params) {
        if (params.get("infoItems") == null || params.get("infoItems") == "") {
            return AjaxResult.error(MessageUtils.message("module.error.lack.infoItems"));
        }
        List<FbaBox> list = JSON.parseArray(params.get("infoItems").toString(), FbaBox.class);
        int count = fbaBoxMapper.countByGuid(list);
        return AjaxResult.success(MessageUtils.message("module.success.issuccess"),count);
    }



    /**
     *@Description: 分箱
     *@Param: [params] moduleTable 必要参数：功能唯一标识
     *@Param: [params] infoMap 必要参数：非网格字段（包括头部、底部所有显示和隐藏的字段）
     *@Param: [params] infoItems 必要参数：对应实体类的json格式字符串
     *@return: com.dhecp.common.core.domain.AjaxResult
     *@Author: fxz
     *@date: 2023-03-16 09:55
     */
    @SuppressWarnings("unchecked")
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public AjaxResult binningEditpost(Map<String, Object> params) throws Exception {
        if (params.get("infoItems") == null || params.get("infoItems") == "") {
            return AjaxResult.error(MessageUtils.message("module.error.lack.infoItems"));
        }
        FbaBox fbaBox = JSON.parseObject(params.get("infoMap").toString(), FbaBox.class);
        FbaBox fbaBox1 = fbaBoxMapper.queryFirstByGuid(fbaBox.getGuid());
        if (!fbaBox1.getState().equals("2")){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error(fbaBox1.getCode()+"该头程装箱单是装箱状态下,请核实后在操作!");
        }
        if (fbaBox1.getIsBinning().equals("是")){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error(fbaBox1.getCode()+"该头程装箱单已分箱,不允许分箱,请核实后在操作!");
        }

        Map<String, Object> params11 = new HashMap<String, Object>();
        params11.put("guid",fbaBox1.getLogisticsMmodeGuid());
        //查询物流方式
        LogisticsMmode logisticsMmode = logsticsMmodeMapper.queryFirstByGuid(params11);
        //获取物流方式详情
        Map<String, Object> params4 = new HashMap<String, Object>();
        params4.put("logisticsMmodeGuid",fbaBox1.getLogisticsMmodeGuid());
        List<LogisticsMmodeDetails> textureList = logsticsMmodeDetailsMapper.findLogisticsMmodeDetails(params4);
        //获取物流方式梯度
        List<LogisticsMmodeGrads> logisticsMmodeGradList = logsticsMmodeGradsMapper.findLogisticsMmodeGrads(params4);
        List<LogisticsMmodeGrads> logisticsMmodeGrads  = logisticsMmodeGradList.stream().filter(logisticsMmodeGrads1 ->
                "WLFS".equals(logisticsMmodeGrads1.getType())).collect(Collectors.toList());
        List<LogisticsMmodeGrads> logisticsMmodeInfoItems  = logisticsMmodeGradList.stream().filter(logisticsMmodeGrads1 ->
                "WLFSTDJZ".equals(logisticsMmodeGrads1.getType())).collect(Collectors.toList());
        List<LogisticsMmodeCk> logisticsMmodeCkList = logsticsMmodeCkMapper.findLogisticsMmodeCk(params4);

        params4.remove("logisticsMmodeGuid");
        params4.put("type","WLPMTD");
        //获取品名梯度详情
        List<LogisticsMmodeGrads> wlpmtdList = logsticsMmodeGradsMapper.findLogisticsMmodeGrads(params4);

        //查询详情信息
        Map<String, Object> params2 = new HashMap<String, Object>();
        params2.put("codeShipment",fbaBox1.getCodeShipment());
        List<FbaBoxDetail> fbaBoxDetailList = fbaBoxDetailMapper.findFbaBoxDetail(params2);

        JSONArray jsonArray = JSON.parseArray(params.get("infoItems").toString());
        JSONObject jsonObject;
        List<FbaBoxDetail> fbaBoxDetailListNew;
        List<FbaBoxDetail> fbaBoxDetailListInset = new ArrayList<>();
        //历史的商品信息
        List<FbaBoxDetail> fbaBoxDetailListOld;
        FbaBox fbaBoxNew;
        List<FbaBoxDetail> boxDetailList;
        BigDecimal weightReal;
        BigDecimal weightVol;
        BigDecimal predVal;
        BigDecimal weightCal;
        BigDecimal weightCalNew;
        BigDecimal max_result;
        BigDecimal texture;
        BigDecimal weightPrice;
        BigDecimal phweightPrice;
        BigDecimal priceClearanceOpePrice;
        BigDecimal tradeNamePro;
        Boolean numWeightCal;
        Integer numProName;
        Integer num;
        Double numFreeProName;
        BigDecimal priceTranCalWeightPredict;
        BigDecimal warehouseSurcharge;
        BigDecimal weightVolPredictNew;
        String surchargeMaterialMax;
        BigDecimal weightCalBySingle;
        List<LogisticsMmodeGrads> tdjzPrice;
        List<LogisticsMmodeGrads> pzjzPrice;
        List<LogisticsMmodeGrads> phjzPrice;
        List<LogisticsMmodeGrads> qgPrice;
        Set<String> gradeNum;
        List<Integer> planNum  =  new ArrayList<>();
        Map<Integer,Integer> planTol;
        ModuleNidAndBid moduleNidAndBid = null;
        for (int i = 0; i < jsonArray.size(); i++) {
            jsonObject = JSONObject.parseObject(String.valueOf(jsonArray.get(i)));
            fbaBoxDetailListNew = JSON.parseArray(jsonObject.get("list").toString(), FbaBoxDetail.class);

            fbaBoxNew = new FbaBox();
            BeanUtils.copyProperties(fbaBox1,fbaBoxNew);
            fbaBoxNew.setIsBinning("是");
            fbaBoxNew.setBinningSource(fbaBox1.getCode());
            fbaBoxNew.setBinningUser(ShiroUtils.getMandatorId());
            fbaBoxNew.setBinningTime(new Date());
            if (i != 0){
                //新增装箱单
                Map<String, Object> params3;
                //查询头程货件最新数据
                params3 = new HashMap<String, Object>();
                params3.put("moduleTable", moduleTableBOX);
                moduleNidAndBid = moduleNidAndBidMapper.findModuleNidAndBid(params3);    //有事务控制，制单异常不跳过单号
                //新增头程装箱单
                fbaBoxNew.setGuid(RandomValueUtils.getGUID());
                fbaBoxNew.setNid(moduleNidAndBid.getNid());
                fbaBoxNew.setBid(moduleNidAndBid.getBid());
                fbaBoxNew.setCode(moduleNidAndBid.getBid());
            }

            //总箱重
            weightReal = BigDecimal.ZERO;
            //总抛重
            weightVol = BigDecimal.ZERO;
            //最大的材质值
            texture = BigDecimal.ZERO;
            //最大值材质名称
            surchargeMaterialMax = "";
            //实际计重之和
            weightCal = BigDecimal.ZERO;
            //最大值
            max_result = BigDecimal.ZERO;
            //实际计重约分
            weightCalNew = BigDecimal.ZERO;
            //抛货系数
            predVal = BigDecimal.ZERO;
            //计重单价
            weightPrice = BigDecimal.ZERO;
            //抛重梯度计重单价
            weightVolPredictNew = BigDecimal.ZERO;
            //抛重计重单价
            phweightPrice = BigDecimal.ZERO;
            //实际计重费
            priceTranCalWeightPredict = BigDecimal.ZERO;
            //仓库附加计重费用
            warehouseSurcharge = BigDecimal.ZERO;
            //品名数除上限数
            tradeNamePro = BigDecimal.ZERO;
            //清关费
            priceClearanceOpePrice = new BigDecimal(100);
            //品名判断数值
            numWeightCal = true;
            //实际品名数
            numProName = 0;
            //超出品名
            num = 0;
            //实际品名免费数
            numFreeProName = 0.0;
            //抛货值
            weightVolPredictNew = BigDecimal.ZERO;
            //品名数量
            gradeNum = new HashSet<>();
            planTol = new HashMap<>();
            for (int boxIndex = 0; boxIndex < fbaBoxDetailListNew.size(); boxIndex++) {
                //实际的商品信息
                fbaBoxDetailListOld = JSON.parseArray(fbaBoxDetailListNew.get(boxIndex).getProductInfo(), FbaBoxDetail.class);
                //拆分对应的每箱的发货数量
                for (int j = 0; j < fbaBoxDetailListOld.size(); j++) {
                    updateFbaBoxDetailNew(boxIndex, fbaBoxDetailListOld.get(j),
                            planNum,fbaBoxDetailListNew,j,i,jsonArray,fbaBoxDetailListOld.size(),planTol);
                }
            }
            for (int boxIndex = 0; boxIndex < fbaBoxDetailListNew.size(); boxIndex++) {
                //实际的商品信息
                fbaBoxDetailListOld = JSON.parseArray(fbaBoxDetailListNew.get(boxIndex).getProductInfo(), FbaBoxDetail.class);
                //将箱子的值根据箱子重新赋值
                for (int j = 0; j < fbaBoxDetailListOld.size(); j++) {
                    updateFbaBoxDetailNew1(fbaBoxDetailListOld.get(j),
                            planNum,j,i,jsonArray,planTol);
                }
                //计算抛重和实重的数据和采购价
                List<FbaBoxDetail> finalFbaBoxDetailListNew = fbaBoxDetailListNew;
                int finalBoxIndex = boxIndex;
                boxDetailList = fbaBoxDetailList.stream().filter(fbaBoxDetail2 -> fbaBoxDetail2.getGuid().equals(finalFbaBoxDetailListNew.get(finalBoxIndex).getGuid())).collect(Collectors.toList());
                weightReal = weightReal.add(new BigDecimal(boxDetailList.get(0).getWeight()));
                weightVol = weightVol.add(new BigDecimal(boxDetailList.get(0).getWeightVol()));
                //MAX（单箱抛重，单箱起重）
                weightVolPredictNew = weightVolPredictNew.add(logisticsMmode.getWeightCalBySingle().max(new BigDecimal(boxDetailList.get(0).getWeightVol())));

                //物流方式==是
                if (fbaBoxNew.getStateShareTicketName().equals("是")) {
                    if (fbaBoxNew.getLogisticsType().equals("快递")) {
                        //实际计重=MAX（实重,抛重,单箱起重）
                        max_result = logisticsMmode.getWeightCalBySingle().max(new BigDecimal(boxDetailList.get(0).getWeight()));
                        max_result = max_result.max(new BigDecimal(boxDetailList.get(0).getWeightVol()));
                        //实际计重之和
                        weightCal = weightCal.add(precision(max_result));
                    }else {
                        //实际计重=MAX（实重,单箱起重）
                        max_result = logisticsMmode.getWeightCalBySingle().max(new BigDecimal(boxDetailList.get(0).getWeight()));
                        //实际计重之和
                        weightCal = weightCal.add(max_result);
                    }
                } else {
                    if (fbaBoxNew.getLogisticsType().equals("快递")) {
                        //实际计重=MAX（实重,抛重,单箱起重）
                        max_result = logisticsMmode.getWeightCalBySingle().max(new BigDecimal(boxDetailList.get(0).getWeight()));
                        max_result = max_result.max(new BigDecimal(boxDetailList.get(0).getWeightVol()));
                        //实际计重之和
                        weightCal = weightCal.add(precision(max_result));
                        fbaBoxNew.setWeightCalA1(weightCal);
                        //实际计重=MAX（A1，单票起重）
                        weightCal = logisticsMmode.getSinglePassCrane().max(weightCal);
                    }else {
                        //实际计重=MAX（实重,抛重,单箱起重）
                        max_result = logisticsMmode.getWeightCalBySingle().max(new BigDecimal(boxDetailList.get(0).getWeight()));
                        max_result = max_result.max(new BigDecimal(boxDetailList.get(0).getWeightVol()));
                        //实际计重之和
                        weightCal = weightCal.add(new BigDecimal(Math.ceil(new Double(String.valueOf(max_result)))));
                        fbaBoxNew.setWeightCalA1(weightCal);
                        //实际计重=MAX（A1，单票起重）
                        weightCal = logisticsMmode.getSinglePassCrane().max(weightCal);
                    }
                }

                //重新计算是第几箱子
                fbaBoxDetailListNew.get(boxIndex).setBoxIndex(boxIndex);
                //重新归属头程箱号
                if (i != 0){
                    fbaBoxDetailListNew.get(boxIndex).setCodeBox(moduleNidAndBid.getBid());
                }
                //去掉箱子中没有数量的商品信息
                fbaBoxDetailListOld = fbaBoxDetailListOld.stream().filter(
                        fbaBoxDetail1 -> !fbaBoxDetail1.getNumRealityDeliver().equals("")
                                || (!fbaBoxDetail1.getNumPlanDeliver().equals("0")  && !fbaBoxDetail1.getNumPlanDeliver().equals(""))
                ).collect(Collectors.toList());
                for (FbaBoxDetail  fbaBoxDetail1 : fbaBoxDetailListOld){
                    //TODO 判断十个箱子里面的值是否有值 再来判断是否需要判断品名数
                    //不一样的品名数=(商品中文、海关编码、材质中文只要一个不同)
                    String join = fbaBoxDetail1.getNameGoodsCn() + '-' + fbaBoxDetail1.getCodeGoodsHs() + '-' +fbaBoxDetail1.getNameMaterialCn();
                    gradeNum.add(join);

                    //判断是否是混合材质
                    //TODO 判断十个箱子里面的值是否有值 再来判断是否需要判断材质值
                    if (fbaBoxDetail1.getNameMaterialCn().indexOf(",") == -1) {
                        //赋值材质附加费(取最大值)
                        for (int j = 0; j < textureList.size(); j++) {
                            if (textureList.get(j).getMaterialName().equals(fbaBoxDetail1.getNameMaterialCn())) {
                                if (textureList.get(j).getMaterialCost().compareTo(texture) > 0) {
                                    texture = (textureList.get(j).getMaterialCost());
                                    surchargeMaterialMax = (textureList.get(j).getMaterialName());
                                }
                            }
                        }
                    } else {
                        String[] nameMaterialCnList = fbaBoxDetail1.getNameMaterialCn().split(",");
                        for (String nameMaterialCn : nameMaterialCnList){
                            for (int j = 0; j < textureList.size(); j++) {
                                if (textureList.get(j).getMaterialName().equals(nameMaterialCn)) {
                                    if (textureList.get(j).getMaterialCost().compareTo(texture) > 0) {
                                        texture = (textureList.get(j).getMaterialCost());
                                        surchargeMaterialMax = (textureList.get(j).getMaterialName());
                                    }
                                }
                            }
                        }
                    }
                }

                //重新赋值商品和箱子数据
                fbaBoxDetailListNew.get(boxIndex).setProductInfo(JSONArray.toJSONString(fbaBoxDetailListOld));
                fbaBoxDetailListInset.add(fbaBoxDetailListNew.get(boxIndex));
            }

            //约分
            weightVolPredictNew = precision(weightVolPredictNew);

            //是否拼票是
            if (fbaBoxNew.getStateShareTicketName().equals("是")) {
                //计重约分
                if (fbaBoxNew.getLogisticsType().equals("快递")) {
                    weightCalNew = weightCal;
                }else {
                    weightCalNew = precision(weightCal);
                }
                //梯度计重单价=(实际计重满足区间的值)
                BigDecimal finalWeightCalNew = weightCalNew;
                tdjzPrice = logisticsMmodeGrads.stream().filter(logisticsMmodeGrads1 -> finalWeightCalNew.compareTo(logisticsMmodeGrads1.getStartSection()) >= 0
                        && finalWeightCalNew.compareTo(logisticsMmodeGrads1.getEndSection()) <= 0).collect(Collectors.toList());
                //抛货系数=(抛重的值--实际计重)
                predVal = (weightVol.subtract(weightCalNew)).setScale(2, BigDecimal.ROUND_HALF_UP);
                //抛货计重单价=(抛货系数满足区间的值)
                BigDecimal finalPredVal = predVal;
                pzjzPrice = logisticsMmodeInfoItems.stream().filter(logisticsMmodeGrads1 -> finalPredVal.compareTo(logisticsMmodeGrads1.getStartSection()) >= 0
                        && finalPredVal.compareTo(logisticsMmodeGrads1.getEndSection()) <= 0).collect(Collectors.toList());
                //计重单价=梯度计重单价+抛重计重单价
                weightPrice = (tdjzPrice.size()!=0?tdjzPrice.get(0).getKg():BigDecimal.ZERO).add(pzjzPrice.size()!=0?pzjzPrice.get(0).getKg():BigDecimal.ZERO);

                phweightPrice = (tdjzPrice.size()!=0?tdjzPrice.get(0).getKg():BigDecimal.ZERO);

                //抛重>实重，实际计重费=MIN(实际计重*计重单价,抛货计重费)；抛重<实重，实际计重费=实际计重*计重单价；
                priceTranCalWeightPredict = (weightCalNew.multiply(weightPrice)).setScale(2, BigDecimal.ROUND_HALF_UP);
                if (weightVol.compareTo(weightReal) > 0){
                    if (priceTranCalWeightPredict.compareTo(weightVolPredictNew.multiply(phweightPrice))>=0){
                        fbaBoxNew.setPriceTranCalWeightPredict(weightVolPredictNew.multiply(phweightPrice));
                    }else {
                        fbaBoxNew.setPriceTranCalWeightPredict(priceTranCalWeightPredict);
                    }
                }else {
                    fbaBoxNew.setPriceTranCalWeightPredict(priceTranCalWeightPredict);
                }

                //1.实际计重<单票起重的二分之一,实际品名数=免费品名数/2&向下取整
                numWeightCal = weightCalNew.compareTo(fbaBoxNew.getSinglePassCrane().divide(new BigDecimal(2)))<0;
                //实际品名数
                numProName = gradeNum.size();
                if (numWeightCal){
                    numFreeProName = Math.floor(Double.valueOf(fbaBoxNew.getNumFreeProNameNew())/2.0);
                }
                //2.实际计重>=单票起重的二分之一,实际品名数=免费品名数/2&向上取整
                if (!numWeightCal && weightCalNew.compareTo(fbaBoxNew.getSinglePassCrane())<0){
                    numFreeProName = Math.ceil(Double.valueOf(fbaBoxNew.getNumFreeProNameNew())/2.0);
                }
                if (weightCalNew.compareTo(fbaBoxNew.getSinglePassCrane()) >= 0){
                    //3.实际计重>=单票起重,实际品名数=免费品名数
                    numFreeProName = fbaBoxNew.getNumFreeProNameNew().doubleValue();
//                    numProName = numFreeProName.intValue();
                }
                //超出品名=实际品名-实际免费品名数
                num = numProName-numFreeProName.intValue();
                //品名免费数
                fbaBoxNew.setNumFreeProName(String.valueOf(numFreeProName.intValue()));
                fbaBoxNew.setNumProName(numProName);
                //清关费=清关费*清关占比
                if (fbaBoxNew.getNumMaxProName()!= 0){
                    //品名数/上限数
                    tradeNamePro = new BigDecimal(gradeNum.size()).divide(new BigDecimal(logisticsMmode.getNumMaxProName()),2,RoundingMode.HALF_UP);
                    BigDecimal finalTradeNamePro = tradeNamePro;
                    qgPrice = wlpmtdList.stream().filter(logisticsMmodeGrads1 -> finalTradeNamePro.compareTo(logisticsMmodeGrads1.getStartSection()) >= 0
                            && finalTradeNamePro.compareTo(logisticsMmodeGrads1.getEndSection()) <= 0).collect(Collectors.toList());
                    priceClearanceOpePrice = qgPrice.size()!=0?qgPrice.get(0).getKg():BigDecimal.ZERO;
                }
                //预估清光费(物流方式清光费*品名占比)
                fbaBoxNew.setPriceClearanceOpe((logisticsMmode.getPriceClearanceOpe().multiply(priceClearanceOpePrice)).divide(new BigDecimal(100),2,RoundingMode.HALF_UP));
                //清光费单价
                fbaBoxNew.setPriceClearanceOpePrice(logisticsMmode.getPriceClearanceOpe());
                fbaBoxNew.setTradeNamePro(priceClearanceOpePrice);
            } else {
                //计重约分
                if (fbaBoxNew.getLogisticsType().equals("快递")) {
                    weightCalNew = weightCal;
                }else {
                    weightCalNew = new BigDecimal(Math.ceil(weightCal.doubleValue()));
                    fbaBox1.setWeightCalA1(weightCalNew);
                    //实际计重=MAX（A1，单票起重）
                    weightCalNew = logisticsMmode.getSinglePassCrane().max(weightCalNew);
                }
                //梯度计重单价=(实际计重满足区间的值)
                BigDecimal finalWeightCalNew = weightCalNew;
                tdjzPrice = logisticsMmodeGrads.stream().filter(logisticsMmodeGrads1 -> finalWeightCalNew.compareTo(logisticsMmodeGrads1.getStartSection()) >= 0
                        && finalWeightCalNew.compareTo(logisticsMmodeGrads1.getEndSection()) <= 0).collect(Collectors.toList());
                //抛货系数=(抛重的值-计重的值)
                predVal = (weightVol.subtract(weightCalNew)).setScale(2, BigDecimal.ROUND_HALF_UP);
                //抛货计重单价=(抛货系数满足区间的值)
                BigDecimal finalPredVal = predVal;
                pzjzPrice = logisticsMmodeInfoItems.stream().filter(logisticsMmodeGrads1 -> finalPredVal.compareTo(logisticsMmodeGrads1.getStartSection()) >= 0
                        && finalPredVal.compareTo(logisticsMmodeGrads1.getEndSection()) <= 0).collect(Collectors.toList());
                //计重单价=梯度计重单价+抛重计重单价
                weightPrice = (tdjzPrice.size()!=0?tdjzPrice.get(0).getKg():BigDecimal.ZERO);

                phweightPrice = (tdjzPrice.size()!=0?tdjzPrice.get(0).getKg():BigDecimal.ZERO);

                //实际计重费=(预估计重*计重单价)
                fbaBoxNew.setPriceTranCalWeightPredict(weightCalNew.multiply(weightPrice));
                numFreeProName = logisticsMmode.getNumFreeProName().doubleValue();
                //超出品名=实际品名-实际免费品名数
                num = gradeNum.size()-logisticsMmode.getNumFreeProName();
                //品名免费数
                fbaBoxNew.setNumFreeProName(logisticsMmode.getNumFreeProName().toString());
                fbaBoxNew.setNumProName(gradeNum.size());
                //实际清光费
                fbaBoxNew.setPriceClearanceOpe(logisticsMmode.getPriceClearanceOpe());
                //清光费单价
                fbaBoxNew.setPriceClearanceOpePrice(logisticsMmode.getPriceClearanceOpe());
                fbaBoxNew.setTradeNamePro(priceClearanceOpePrice);
            }

            List<LogisticsMmodeCk> logisticsMmodeCkS = new ArrayList<>();
            if (logisticsMmodeCkList.size() != 0){
                FbaBox finalFbaBoxNew = fbaBoxNew;
                logisticsMmodeCkS  = logisticsMmodeCkList.stream().filter(logisticsMmodeCk ->
                        finalFbaBoxNew.getDestinationFulfillmentCenterId().equals(logisticsMmodeCk.getWarehouseName())).collect(Collectors.toList());
            }

            if (logisticsMmodeCkS.size() != 0){
                fbaBoxNew.setWarehouseSurchargePrice(logisticsMmodeCkS.get(0).getWarehouseCost());
            }else {
                fbaBoxNew.setWarehouseSurchargePrice(BigDecimal.ZERO);
            }
//            //仓库附加计重费用 = 仓库附件计重单价*实际计重
//            warehouseSurcharge = (weightCalNew.multiply(fbaBoxNew.getWarehouseSurchargePrice())).setScale(2, BigDecimal.ROUND_HALF_UP);
//            fbaBoxNew.setWarehouseSurcharge(warehouseSurcharge);
//            fbaBoxNew.setPriceTranCalWeightPredict(fbaBoxNew.getPriceTranCalWeightPredict().add(warehouseSurcharge));

            //实际实重
            fbaBoxNew.setWeightReal(weightReal);
            //实际抛重
            fbaBoxNew.setWeightVol(weightVol);
            //装箱计重
            fbaBoxNew.setWeightCal(weightCalNew);
            //头程箱数
            fbaBoxNew.setNumBox(fbaBoxDetailListNew.size());
            //抛货系数
            fbaBoxNew.setJettisonCoe(predVal);
            //梯度计重单价
            fbaBoxNew.setTdjzPrice(tdjzPrice.size()!=0?tdjzPrice.get(0).getKg():BigDecimal.ZERO);
            //抛货计重单价
            fbaBoxNew.setPzjzPrice(pzjzPrice.size()!=0?pzjzPrice.get(0).getKg():BigDecimal.ZERO);
            //计重单价
            fbaBoxNew.setJzPrice(weightPrice);
            //抛货计重费
            fbaBoxNew.setJettisonWeightCharge(weightVolPredictNew.multiply(phweightPrice).setScale(2, BigDecimal.ROUND_HALF_UP));
            //设置表头附加费材质
            fbaBoxNew.setPriceQualityExtra(texture);
            //最大附加费材质
            fbaBoxNew.setSurchargeMaterialMax(surchargeMaterialMax);
            //设置实际材质附加费=材质计费*实际计重
            fbaBoxNew.setPriceQualityExtraPredict(texture.multiply(weightCalNew).setScale(2, BigDecimal.ROUND_HALF_UP));
            //品名
            fbaBoxNew.setNumProNameBeyond(num>0?num:0);
            //占比
            fbaBoxNew.setTradeNamePro(priceClearanceOpePrice);
            //实际品名附加费 = 超出的品名*品名标准
            fbaBoxNew.setPriceProNameExtraPredict(logisticsMmode.getPriceProNamePerOne().multiply(new BigDecimal(fbaBoxNew.getNumProNameBeyond())).setScale(2, BigDecimal.ROUND_HALF_UP));
            //实际物流费用 = 实际计重运费+实际材质附加费+实际品名附加费+实际清关费
            fbaBoxNew.setActualLogisticsFreight(fbaBoxNew.getPriceTranCalWeightPredict().
                    add(fbaBoxNew.getPriceQualityExtraPredict()).add(fbaBoxNew.getPriceProNameExtraPredict()
                    .add(fbaBoxNew.getPriceClearanceOpe())));

            //判断是否是抛重发货 -- 进行逻辑计算
            if (fbaBoxNew.getLoadDelivery().equals("是")){
                //实际抛发清关费=清关费单价
                fbaBoxNew.setPriceClearanceOpePf(logisticsMmode.getPriceClearanceOpe());
                //抛发实际品名免费数=品名免费数
                fbaBoxNew.setNumFreeProNamePf(logisticsMmode.getNumFreeProName());
                //抛发超品名数量【=实际品名数-抛发实际品名免费数】
                int numPf = fbaBoxNew.getNumProName() - fbaBoxNew.getNumFreeProNamePf();
                numPf = numPf>0?numPf:0;
                //实际抛发品名附加费、费用说明：实际抛发品名附加费=超品名数量*品名附加费单价
                fbaBoxNew.setPriceProNameExtraPredictPf(logisticsMmode.getPriceProNamePerOne().multiply(new BigDecimal(numPf)).setScale(2, BigDecimal.ROUND_HALF_UP));
                //抛发计重：【=MAX（装箱抛重，单票起重）约分】
                BigDecimal weightCalPf = precision(logisticsMmode.getSinglePassCrane().max(weightVol));
                //实际抛发材质附加费、费用说明：实际抛发材质附加费=MAX（装箱抛重，单票起重）*材质附加单价
                fbaBoxNew.setPriceQualityExtraPredictPf(weightCalPf.multiply(fbaBoxNew.getPriceQualityExtra()).setScale(2, BigDecimal.ROUND_HALF_UP));
                //抛发计重单价：【抛发计重对应的梯度价】
                List<LogisticsMmodeGrads> pfLogisticsMmodeGrads;
                BigDecimal pfjzPrice;
                pfLogisticsMmodeGrads = logisticsMmodeGrads.stream().filter(logisticsMmodeGrads1 -> weightCalPf.compareTo(logisticsMmodeGrads1.getStartSection()) >= 0
                        && weightCalPf.compareTo(logisticsMmodeGrads1.getEndSection()) <= 0).collect(Collectors.toList());
                pfjzPrice = (pfLogisticsMmodeGrads.size()!=0?pfLogisticsMmodeGrads.get(0).getKg():BigDecimal.ZERO);
                //实际抛发计重运费、费用说明：实际抛发计重运费=MAX（装箱抛重，单票起重）*抛发计重单价
                fbaBoxNew.setPriceTranCalWeightPredictPf(((weightCalPf.multiply(pfjzPrice))).setScale(2, BigDecimal.ROUND_HALF_UP));
                //实际抛发物流运费、费用说明：实际抛发物流运费=实际抛发计重运费+实际抛发材质附加费+实际抛发品名附加费+实际抛发清关费
                fbaBoxNew.setActualLogisticsFreightPf(fbaBoxNew.getPriceTranCalWeightPredictPf()
                        .add(fbaBoxNew.getPriceQualityExtraPredictPf())
                        .add(fbaBoxNew.getPriceProNameExtraPredictPf())
                        .add(fbaBoxNew.getPriceClearanceOpePf()));
            }

            //0原单据，清空分箱出去的数据,其它划分其他单据
            if (i != 0){
                fbaBoxMapper.insertFbaBox(fbaBoxNew);
            } else {
                fbaBoxMapper.updateByGuid(fbaBoxNew);
            }
        }

        //批量修改箱子
        fbaBoxDetailMapper.batchUpdate(fbaBoxDetailListInset);
        return AjaxResult.success("分箱成功");
    }

    private BigDecimal precision(BigDecimal f){
        //根据数字未满5满5,未满10满10
        String s = f.stripTrailingZeros().toPlainString();
        String ff = f.toString();
        int rs = s.indexOf(".");
        if (rs != -1) {
            //取出第一位
            String first = s.substring(0,rs);
            //根据第一位小数5来判断，大于0.5以上进1,小于0.5的为0.5
            first = first + ".5";
            Double fD = Double.parseDouble(String.valueOf(f));
            Double firstD = Double.parseDouble(first);
            if (fD < firstD){
                ff = first;
            } else if(fD > firstD) {
                ff = String.valueOf(Math.round(fD));
            }
        }
        return new BigDecimal(ff);
    }


    /**
     * 计算每箱需要拆分的计划发货数量合计
     * @param boxIndex  每箱的当前下标
     * @param fbaBoxDetailListRealityNew  实际的商品下标信息
     * @param planNum  由最初发货数量逐渐扣减
     * @param fbaBoxDetailListNew 每箱对应的所有数据（此处只是用于size）
     * @param boxI  每箱对应商品信息的下标（用于判断存放planTol,planNum的值）
     * @param i 所有分箱的数据下标
     * @param jsonArray 所有分箱的数据
     * @param sizo 商品总数量
     * @param planTol 每一箱的计划发货数量之和
     */
    private void updateFbaBoxDetailNew(Integer boxIndex, FbaBoxDetail fbaBoxDetailListRealityNew, List<Integer> planNum
            , List<FbaBoxDetail> fbaBoxDetailListNew
            ,Integer boxI,Integer i,JSONArray jsonArray,Integer sizo,Map<Integer,Integer> planTol){
        String theCase = fbaBoxDetailListRealityNew.getNumRealityDeliver();
        //记录最初的计划发货数量
        if (planNum.size() < sizo ){
            planNum.add(Integer.valueOf(fbaBoxDetailListRealityNew.getNumPlanDeliver()));
        }
        //第一箱的数据
        if (i == 0){
            //将每一箱当中的实际箱子数量合计
            planTol.put(boxI,(planTol.get(boxI)== null?0:planTol.get(boxI)) + Integer.valueOf(theCase.equals("")?"0":theCase));
            if (fbaBoxDetailListNew.size()-1 == boxIndex){
                //每箱里面是最后一条则进行计划发货数量的数据扣减当前的实际单箱发货总数量
                planNum.set(boxI,planNum.get(boxI) - planTol.get(boxI));
            } else if (fbaBoxDetailListNew.size() == 1){
                //每箱里面是最后一条则进行计划发货数量的数据扣减当前的实际单箱发货总数量
                planNum.set(boxI,planNum.get(boxI) - planTol.get(boxI));
            }
        }else if (jsonArray.size()-1 != i){//中间的箱子数据
            //将每一箱当中的实际箱子数量合计
            planTol.put(boxI,(planTol.get(boxI)== null?0:planTol.get(boxI)) + Integer.valueOf(theCase.equals("")?"0":theCase));
            if (fbaBoxDetailListNew.size()-1 == boxIndex){
                //每箱里面是最后一条则进行计划发货数量的数据扣减当前的实际单箱发货总数量
                planNum.set(boxI,planNum.get(boxI) - planTol.get(boxI));
            } else if (fbaBoxDetailListNew.size() == 1){
                //每箱里面是最后一条则进行计划发货数量的数据扣减当前的实际发货数量
                planNum.set(boxI,planNum.get(boxI) - Integer.valueOf(theCase));
            }
        }
    }

    private void updateFbaBoxDetailNew1( FbaBoxDetail fbaBoxDetailReality,
                                         List<Integer> planNum
            ,Integer boxI,Integer i,JSONArray jsonArray,Map<Integer,Integer> planTol){
        //当不是最后一条数据
        if (i == 0){
            fbaBoxDetailReality.setNumPlanDeliver(planTol.get(boxI).toString());
        }else if (jsonArray.size()-1 != i){
            fbaBoxDetailReality.setNumPlanDeliver(planTol.get(boxI).equals(0)?"":planTol.get(boxI).toString());
        } else {
            fbaBoxDetailReality.setNumPlanDeliver(planNum.get(boxI).toString());
        }
    }

    private void updateFbaBoxDetail(Integer boxIndex, FbaBoxDetail fbaBoxDetail, FbaBoxDetail fbaBoxDetailReality,
                                    FbaBoxDetail fbaBoxDetailListRealityNew, List<Integer> planNum, List<FbaBoxDetail> fbaBoxDetailListNew
            ,Integer boxI,Integer i,JSONArray jsonArray,Integer sizo,Map<String,Integer> planTol){
        String theCase = "";
        if (fbaBoxDetail.getBoxIndex() == 0){
            theCase = (fbaBoxDetailListRealityNew.getTheFirstCase());
        }
        if (fbaBoxDetail.getBoxIndex() == 1){
            theCase = (fbaBoxDetailListRealityNew.getTheSecondCase());
        }
        if (fbaBoxDetail.getBoxIndex() == 2){
            theCase = (fbaBoxDetailListRealityNew.getTheThirdCase());
        }
        if (fbaBoxDetail.getBoxIndex() == 3){
            theCase = (fbaBoxDetailListRealityNew.getTheFourCase());
        }
        if (fbaBoxDetail.getBoxIndex() == 4){
            theCase = (fbaBoxDetailListRealityNew.getTheFiveCase());
        }
        if (fbaBoxDetail.getBoxIndex() == 5){
            theCase = (fbaBoxDetailListRealityNew.getTheFixCase());
        }
        if (fbaBoxDetail.getBoxIndex() == 6){
            theCase = (fbaBoxDetailListRealityNew.getTheSevenCase());
        }
        if (fbaBoxDetail.getBoxIndex() == 7){
            theCase = (fbaBoxDetailListRealityNew.getTheEightCase());
        }
        if (fbaBoxDetail.getBoxIndex() == 8){
            theCase = (fbaBoxDetailListRealityNew.getTheNineCase());
        }
        if (fbaBoxDetail.getBoxIndex() == 9){
            theCase = (fbaBoxDetailListRealityNew.getTheTenCase());
        }
        //记录开始计划发货数量
        if (planNum.size() < sizo ){
            planNum.add(Integer.valueOf(fbaBoxDetailReality.getNumPlanDeliver()));
        }
        //当不是最后一条数据
        if (i == 0){
            //将每一箱分箱当中的箱子合计
            planTol.put(String.valueOf(boxI),(planTol.get(String.valueOf(boxI))== null?0:planTol.get(String.valueOf(boxI))) + Integer.valueOf(theCase.equals("")?"0":theCase));
            if (fbaBoxDetailListNew.size()-1 == boxIndex){
                //判断每箱里面是最后一条则进行计划发货数量的数据跟变
                planNum.set(boxI,planNum.get(boxI) - planTol.get(String.valueOf(boxI)));
                fbaBoxDetailReality.setNumPlanDeliver(planTol.get(String.valueOf(boxI)).toString());
            } else if (fbaBoxDetailListNew.size() == 1){
                planNum.set(boxI,planNum.get(boxI) - planTol.get(String.valueOf(boxI)));
            }
        }else if (jsonArray.size()-1 != i){
            //将每一箱分箱当中的箱子合计
            planTol.put(String.valueOf(boxI),(planTol.get(String.valueOf(boxI))== null?0:planTol.get(String.valueOf(boxI))) + Integer.valueOf(theCase.equals("")?"0":theCase));
            if (fbaBoxDetailListNew.size()-1 == boxIndex){
                //判断每箱里面是最后一条则进行计划发货数量的数据跟变
                planNum.set(boxI,planNum.get(boxI) - planTol.get(String.valueOf(boxI)));
                fbaBoxDetailReality.setNumPlanDeliver(planTol.get(String.valueOf(boxI)).equals(0)?"":planTol.get(String.valueOf(boxI)).toString());
            } else if (fbaBoxDetailListNew.size() == 1){
                planNum.set(boxI,planNum.get(boxI) - Integer.valueOf(theCase));
            }
        } else {
            //当不是最后一条，且又是最后一条商品数据，则更改计划发货数量
            if (fbaBoxDetailListNew.size()-1 == boxIndex){
                fbaBoxDetailReality.setNumPlanDeliver(planNum.get(boxI).toString());
            }
        }

        //每条商品去取对应箱子数据的值
        if (boxIndex == 0){
            fbaBoxDetailReality.setTheFirstCase(theCase);
        }else if (boxIndex == 1){
            fbaBoxDetailReality.setTheSecondCase(theCase);
        } else if (boxIndex == 2){
            fbaBoxDetailReality.setTheThirdCase(theCase);
        } else if (boxIndex == 3){
            fbaBoxDetailReality.setTheFourCase(theCase);
        } else if (boxIndex == 4){
            fbaBoxDetailReality.setTheFiveCase(theCase);
        } else if (boxIndex == 5){
            fbaBoxDetailReality.setTheFixCase(theCase);
        } else if (boxIndex == 6){
            fbaBoxDetailReality.setTheSevenCase(theCase);
        } else if (boxIndex == 7){
            fbaBoxDetailReality.setTheEightCase(theCase);
        } else if (boxIndex == 8){
            fbaBoxDetailReality.setTheNineCase(theCase);
        } else if (boxIndex == 9){
            fbaBoxDetailReality.setTheTenCase(theCase);
        }
    }

    private void qkfbaBoxDetailReality(Integer boxIndex,FbaBoxDetail fbaBoxDetailReality) {
        //将其余的箱子数量清空
        if (boxIndex == 0){
            fbaBoxDetailReality.setTheSecondCase("");
            fbaBoxDetailReality.setTheThirdCase("");
            fbaBoxDetailReality.setTheFourCase("");
            fbaBoxDetailReality.setTheFiveCase("");
            fbaBoxDetailReality.setTheFixCase("");
            fbaBoxDetailReality.setTheSevenCase("");
            fbaBoxDetailReality.setTheEightCase("");
            fbaBoxDetailReality.setTheNineCase("");
            fbaBoxDetailReality.setTheTenCase("");
        }
        if (boxIndex == 1){
            fbaBoxDetailReality.setTheThirdCase("");
            fbaBoxDetailReality.setTheFourCase("");
            fbaBoxDetailReality.setTheFiveCase("");
            fbaBoxDetailReality.setTheFixCase("");
            fbaBoxDetailReality.setTheSevenCase("");
            fbaBoxDetailReality.setTheEightCase("");
            fbaBoxDetailReality.setTheNineCase("");
            fbaBoxDetailReality.setTheTenCase("");
        }
        if (boxIndex == 2){
            fbaBoxDetailReality.setTheFourCase("");
            fbaBoxDetailReality.setTheFiveCase("");
            fbaBoxDetailReality.setTheFixCase("");
            fbaBoxDetailReality.setTheSevenCase("");
            fbaBoxDetailReality.setTheEightCase("");
            fbaBoxDetailReality.setTheNineCase("");
            fbaBoxDetailReality.setTheTenCase("");
        }
        if (boxIndex == 3){
            fbaBoxDetailReality.setTheFiveCase("");
            fbaBoxDetailReality.setTheFixCase("");
            fbaBoxDetailReality.setTheSevenCase("");
            fbaBoxDetailReality.setTheEightCase("");
            fbaBoxDetailReality.setTheNineCase("");
            fbaBoxDetailReality.setTheTenCase("");
        }
        if (boxIndex == 4){
            fbaBoxDetailReality.setTheFixCase("");
            fbaBoxDetailReality.setTheSevenCase("");
            fbaBoxDetailReality.setTheEightCase("");
            fbaBoxDetailReality.setTheNineCase("");
            fbaBoxDetailReality.setTheTenCase("");
        }
        if (boxIndex == 5){
            fbaBoxDetailReality.setTheSevenCase("");
            fbaBoxDetailReality.setTheEightCase("");
            fbaBoxDetailReality.setTheNineCase("");
            fbaBoxDetailReality.setTheTenCase("");
        }
        if (boxIndex == 6){
            fbaBoxDetailReality.setTheEightCase("");
            fbaBoxDetailReality.setTheNineCase("");
            fbaBoxDetailReality.setTheTenCase("");
        }
        if (boxIndex == 7){
            fbaBoxDetailReality.setTheNineCase("");
            fbaBoxDetailReality.setTheTenCase("");
        }
        if (boxIndex == 8){
            fbaBoxDetailReality.setTheTenCase("");
        }
    }
}
